I have a small dialog frame that appears, and within this frame are a series of buttons and a textbox.
I need the frame to be able to detect when the user has put focus on something else on the screen (being: anything besides the frame and its components), so I can close down the frame.
Any advice on how to go about this? I've been trying at focus solutions for hours, to no solution!
Try using a WindowStateListener
The WindowEvent parameter it provides can tell you if the window has lost focus through the getNewState() method.
class MyFocusLostListener implements WindowStateListener {
public void windowStateChanged(WindowEvent e) {
if (e.getNewState() == WindowEvent.WINDOW_LOST_FOCUS) {
e.getWindow().setVisible(false);
}
}
}
need the frame to be able to detect when the user has put focus on something else on the screen
Use a WindowListener and listen for windowDeactivated.
listen to property changes of the property "permanentFocusOwner" of the KeyboardFocusManager. On being notified, check if the new focusOwner is in the child hierarchy under the frame, if not - close the frame.
Edit: seeing the answers suggesting a Window/StateListener - they are better than mine for a top-level window :-) Listening to the keyboardFocusManager is a good approach for containers deeper down in the hierarchy, implemented f.i. in the CellEditorRemover of a JTable (to decide if a pending edit should be terminated)
Related
I am trying to find a method that can close the active JFrame.
I am unable to use frame.dispose();, as I am declaring the action listener in a toolbar class and the frames I want to close are not static and are declared at runtime.
I have tried using:
java.awt.Window win[] = java.awt.Window.getWindows();
for(int i=0;i<win.length;i++){
win[i].dispose();
}
and whilst this does work, in certain circumstances it will close more than one window even though only 1 window appears to be open, so frames will flash open and closed many times depending on what actions the user has made.
For me to fully recreate my problem would involve posting a significant amount of code which would not be in line with MCVE principles.
I am hoping someone will know of a more simple and reliable way of closing the active frame in the mould of acitveframe.dispose(); - which I now is not a real solution!!
What happens if you try to get the Window ancestor of the source of the action event? i.e.,
#Override
public void actionPerformed(ActionEvent actionEvent) {
Component comp = (Component) actionEvent.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
win.dispose();
}
This won't work if the source is not a Component or if it is not contained within the top level Window of interest.
Regarding:
For me to fully recreate my problem would involve posting a significant amount of code which would not be in line with MCVE principles.
I'll bet with a bit of effort you could create and post something that comes close.
I am hoping someone will know of a more simple and reliable way of closing the active frame
In your loop you can add:
if (window.isActive())
// do something
Or maybe a simpler approach is:
Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
Also, assuming your active window is a JFrame, instead of using window.dispose(), I have used code like:
WindowEvent windowClosing = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
frame.dispatchEvent(windowClosing);
this will simulate the user clicking on the "Close" button which means that any WindowListener you added to the frame will also be executed. See Closing an Appplication for more information and ideas.
When you are declaring your JFrames, declre them as final if you cannot use static :
final JFrame f = new JFrame();
It would solve the problem.
I have multiple JDialogs in my application stored in a map. These JDialogs are all have
setModel(false);
When these dialogs are out of focus and I want to bring a specific JDialog toFront all JDialogs come toFront. I want the specific Jdialog to come to front and want the other JDialogs to remain in back.
HashMap<String, JDialog> jDialogMap = getJDialogMap();
String key = "jd1";
JDialog specificJDialog= jDialogMap.get(key);
if (specificJDialog== null){
specificJDialog= new JDialog();
specificJDialog.setModel(false);
specificJDialog.setVisible(true);
jDialogMap.put("jd2", specificJDialog);
} else {
specificJDialog.toFront();
return;
}
This code brings all the JDialogs toFront having the specificJDialog on top of the stack.
getJDialogMap();
This Method only returns a HashMap nothing else.
use requiredDialogObject.requestFocusInWindow();
whenever u need focus on the specific dialog
I found a solution to my problem I think it is worth sharing it.
Solution: Creating multiple JDilogs in an application with default constructor i.e. new JDialog() will result in a shared frame as the parent of each JDialog which will cause these kind of problems. So I used the overloaded constructor new JDialog(new JFrame()) to have separate parent for each JDialog and that solved my problem.
Had a similar issue. After opening the JDialog my main application window just requested the focus again, moving the JDialog window to the background, which was annoying. I experimented with modal() and toFront() methods, which both didn't work out for me, since modal() just prevented user interaction completely (outside of that JDialog) and toFront() also has effect on windows outside my application (by using it inside of a timer method, see below).
To keep the window in front of the main application I used a timer method, which was fired every 300 ms and just keeps requesting the focus by using the requestFocus() method.
import javax.swing.Timer;
Timer timer = new Timer(300, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
requestFocus();
}
});
timer.start();
In my Java Swing Application Reuestfocus method not working at the Constructor. But it works if I used requestfocus along with button action listener. I want set Requestfocus at the form load. I dont understand whats the wrong here. P.S I use JInternal Frame
txtItemName.requestFocusInWindow (); // did not work
txtItemName.requestFocus (); // did not work
public ItemMgt() {
initComponents();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtItemName.requestFocus(); // did not work
}
});
}
private void formInternalFrameActivated(javax.swing.event.InternalFrameEvent evt) {
txtItemName.requestFocus(); // did not work.
}
The case might by that your component is not visible, so the GUI manager can not set focus on it.
As is specified in documentation:
(..) component must be displayable, focusable, visible and all of its ancestors (with the exception of the top-level Window) must be visible for the request to be granted.
Generally you should avoid to have so robust logic in constructor. Your graphic components should be constructed first. When this is finished they should be adjusted to your preferences.
Instead of requestFocus(), it is recomended to use requestFocusInWindow() for more please visit the tutorial: How to Use the Focus Subsystem
If you are using Netbeans IDE, then its much easier. Just make sure that all controls before your textbox are not focusable by unchecking the 'focusable' property in the Properties window. This will leave your textbox as the first focusable control thus allowing it to receive focus when the internal frame is opened
Hi I have only one JDialog box in my Java application.I want to make it invisible if it lost the focus.
I've tried different method, But didn't able to trigger any of the window focus events. Here is my code:
public void windowGainedFocus(WindowEvent e) {
System.out.println("gained focus");
}
public void windowLostFocus(WindowEvent e) {
System.out.println("lost focus");
}
Responding to Focus events can be really tricky. My experience has been that pretty much any time someone has attempted to do non-standard things with focus, they come to regret it eventually. Not least among the issues is that it's not really all that portable - a lot of X-Windows based displays use focus-follows-mouse, which can result in the focus being transferred away when you're not expecting it to, resulting in early dismissal of your dialog.
That said, Sun's official tutorial is here: http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html . If I remember right, you can attach a PropertyChangeListener to the KeyboardFocusManager, and that will be triggered for focus changes: http://java.sun.com/javase/6/docs/api/java/awt/KeyboardFocusManager.html#addPropertyChangeListener%28java.beans.PropertyChangeListener%29
Use a WindowListener and handle the windowDeactivated event.
I have a JPanel inside a JFrame. I have registered a KeyListener, based on which I want to update the JPanel. The problem I am having is that I cannot get the focus on the JPanel and therefore my KeyListener won't work. I already know that the KeyListener is functional because I registered it with the JFrame and it worked fine. My code goes something like this at the moment:
myFrame.setFocusable(false);
myPanel.setFocusable(true);
myPanel.addKeyListener(myKL);
myFrame.add(myPanel);
Has anyone encountered a problem like this before? Is there something I am missing in regards to this?
P.S.: I do not have any components inside the JPanel I just draw an Image on the background, so I need the focus to be on the JPanel itself and not on something inside it.
Although you're indicating that the panel can be focusable, the panel isn't asking for focus. Try using myPanel.requestFocus();.
Use setFocusable(true) and then requestFocusInWindow(). But the latter must be done after the window containing the panel is made visible, for which you will likely need to register a window listener and do the requestFocusInWindow() in the window activated handler code.
Note: Specifically after the window is visible, not just after calling setVisible(true).
I sometimes face a similar problem. I've noticed that in some cases it is better to make or request focus on a specific control within the panel that is within the frame (e.g., the input box to which you want keyboard input to go), rather than request focus for the pane itself.
Try
panel.setFocusable(true);
panel.setRequestFocusEnabled(true);
// some code here
panel.grabFocus();
Try something like this:
myFrame.addFocusListener(new FocusAdapter() {
/**
* {#inheritDoc}
*/
#Override
public void focusGained(FocusEvent aE) {
myPanel.requestFocusInWindow();
}
});