Skip to main content

Weird Behavior Java Swing Accelerator and Removing A JButton in OSX

Please note these java.net forums are being decommissioned and use the new and improved forums at https://community.oracle.com/community/java.
No replies
sshark
Offline
Joined: 2004-03-31

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 modified the label, it worked perfectly. Where did my code go wrong? I tested my application and this issue occurred only with JDK 1.7 on top of OSX (Mountain Lion). Windows and Linux do not exhibit this problem.

This is just an example. In actual, I have variable number of JLabel and JButton inside the ContentPane. This number of labels and buttons changes depending on input but the total number components is fixed.

Thanks

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;

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();
    }
}