I have a simple Swing application to demonstrate a weird behavior where remove and add a new component i.e. JButton caused the JMenuItem accelerator, "F3" not to response. What I experienced was,
Pressed F3 for the 1st time worked (the JButton label number increase by 1). Pressed F3 repeatedly did not work. If I clicked on a button and pressed F3 again, it worked again.
Next scenario, instead of clicked on the button, I clicked on the menu item "Refresh", pressed F3 repeatedly worked all the way.
If I did not remove the JButton, and just modified the label, there is worked perfectly. Where did my code go wrong? At this moment, I only tested this application with OSX (Mountain Lion) with JDK 1.7 I have yet to try on other OSes. Thanks
Added : This is just an example. In actual, I have variable number of JLabel and JButton inside the ContentPane. This number changes from time to time depending on the circumstances.
public class ClickMeFrame {
private JButton clickMe = new JButton("1");
public ClickMeFrame() {
JFrame app = new JFrame("Numbers Frame");
app.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final Container appContent = app.getContentPane();
clickMe.setSize(new Dimension(20, 20));
appContent.add(clickMe);
JMenuBar menuBar = new JMenuBar();
JMenu file = new JMenu("File");
menuBar.add(file);
AbstractAction refreshAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Refresh");
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
int nextIndex = Integer.parseInt(clickMe.getText()) + 1;
// remove from here
appContent.remove(clickMe);
clickMe = new JButton(nextIndex + "");
appContent.add(clickMe);
// to here to experiment with button text change instead of replacing with a new JButton
// enable me to experiment with button text change instead
//clickMe.setText(nextIndex + "");
appContent.revalidate();
appContent.repaint();
}
});
}
};
JMenuItem refresh = new JMenuItem("Refresh");
refresh.setAccelerator(KeyStroke.getKeyStroke("F3"));
refresh.addActionListener(refreshAction);
file.add(refresh);
app.setJMenuBar(menuBar);
app.pack();
app.setVisible(true);
}
public static void main(String[] args) {
new ClickMeFrame();
}
}