0

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,

  1. 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.

  2. 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();
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
thlim
  • 2,908
  • 3
  • 34
  • 57
  • I don't think there is any point in removing the button if you already know a solutino that works perfectly, viz., using `setText`. – tbodt Jul 21 '13 at 09:29
  • This is just an example. In actual, the number of JLabel and JButton inside the ContentPane will change. Regardless, this should not have happened unless I have made a mistake. – thlim Jul 21 '13 at 09:36
  • Works fine here on JDK7/Windows 7. – JB Nizet Jul 21 '13 at 09:39
  • For many components in one space, use a [`CardLayout`](http://docs.oracle.com/javase/7/docs/api/java/awt/CardLayout.html) as seen in this [short example](http://stackoverflow.com/a/5786005/418556). – Andrew Thompson Jul 21 '13 at 09:53
  • It would use CardLayout if it suitable here. I don't have to keep other layouts and switch between them. Once the layout is outdated, it can be discarded. Just keep the current. – thlim Jul 21 '13 at 10:30
  • @JB The problem could be just limited to OSX. I have yet to test it out in Linux and Windows. – thlim Jul 21 '13 at 11:10
  • @thlim: yes indeed. I just wanted to let you know that it was not happening on all platforms. – JB Nizet Jul 21 '13 at 11:21

0 Answers0