Reputation: 45
I'm trying to programmatically click a JButton, which is fine, the doClick() method works prefectly. The problem is that I want to be able to programmatically click whatever button is currently in focus.
I can programmatically give a button focus just fine with .grabFocus() (at least it would seem so) but for some reason .isFocusOwner() always returns false.
If the code is run you can visually confirm that the button 'b2' is indeed in focus, however both if(frame.getFocusOwner() instanceof JButton) and if(b2.isFocusOwner) return false.
The code below illustrates the problem I'm having.
I imagine I've missed something obvious, but any advice would be fantastic.
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton b1 = new JButton("b1");
JButton b2 = new JButton("b2");
JTextField j1 = new JTextField(10);
b1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Push the button...");
}
});
b2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("...and let it go...");
}
});
panel.add(b1);
panel.add(b2);
panel.add(j1);
frame.add(panel);
frame.setSize(400, 400);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setVisible(true);
//// The two problems are below
// It looks like this does give 'b2' the focus, at least as far as the generated GUI is concerned
b2.grabFocus();
// First - Always returns false
if(frame.getFocusOwner() instanceof JButton) {
JButton focusedButton = (JButton) frame.getFocusOwner();
focusedButton.doClick();
System.out.println("In focus?");
}
else {
System.out.println("Apparently not");
}
// Second - Also always returns false
if(b2.isFocusOwner()) {
System.out.println("In focus...");
}
else {
System.out.println("Not in focus");
}
}
Upvotes: 4
Views: 313
Reputation: 324108
Not all code executes synchronously. Some code get added to the end of the Event Dispatch Thread (EDT)
. It appears that this is the case for focus requests. So when the if statements are executed, focus has not yet been placed on the component.
The solution is to wrap your code with a SwingUtilties.invokeLater()
so the code gets added to the end of the EDT, so it can execute after the component has received focus:
//b2.grabFocus();
b2.requestFocusInWindow();
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
// First - Always returns false
if(frame.getFocusOwner() instanceof JButton) {
JButton focusedButton = (JButton) frame.getFocusOwner();
focusedButton.doClick();
System.out.println("In focus?");
}
else {
System.out.println("Apparently not");
}
// Second - Also always returns false
if(b2.isFocusOwner()) {
System.out.println("In focus...");
}
else {
System.out.println("Not in focus");
}
}
});
Also, don't use grabFocus(), you should use requestFocusInWindow()
. Read the API for more information.
Upvotes: 4