Question

I have written a class that should create abstract menu items using a factory method, but the components never show up in the menubar. I have stepped through the debugger and the properties, such as text, were not being set. I have tried invalidating the component with no luck.

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

public class GameMenu extends JMenuBar {
    private static final long serialVersionUID = -8058207339633024354L;

    private JMenu file;
    private JMenu help;
    private JMenuItem newGame;
    private JMenuItem about;

    private static NewGameAction newGameAction = new NewGameAction();
    private static AboutAction aboutAction = new AboutAction();

    public GameMenu() {
        super();

        file = (JMenu) createButton(JMenu.class, "File",
            KeyEvent.VK_F, this, null);
        help = (JMenu) createButton(JMenu.class, "Help",
            KeyEvent.VK_H, this, null);
        newGame = (JMenuItem) createButton(JMenuItem.class, "New Game",
            KeyEvent.VK_N, file, newGameAction);
        about = (JMenuItem) createButton(JMenuItem.class, "About",
            KeyEvent.VK_A, help, aboutAction);
    }

    @SuppressWarnings("unchecked")
    public <T extends AbstractButton> AbstractButton createButton(
            Class<T> buttonClazz, String text, int mnemonic, JComponent parent,
            Action action) {
        AbstractButton button = null;

        try {
            button = buttonClazz.newInstance();
            button.setText(text);
            button.setMnemonic(mnemonic);
            button.setAction(action);
            button.invalidate();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return (T) parent.add(button);
    }

    private static class AboutAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("About");
        }
    }

    private static class NewGameAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("New Game");
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame("Abstract Menu Test");
                GameMenu menu = new GameMenu();

                f.setJMenuBar(menu);
                f.setSize(300, 200);
                f.setLocationRelativeTo(null);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}

Adding the components manually seems to work fine, but this is not desirable for my situation.

public GameMenu() {
    super();

    file = new JMenu("File");
    file.setMnemonic(KeyEvent.VK_F);
    this.add(file);
}
Was it helpful?

Solution

The problem is probably because you are setting null actions and by that resetting the text and mnemonic on the buttons that are created in createButton(). Comment out the following line:

button.setAction(action);

And you should see the menu OK.

enter image description here

See How to Use Actions for some examples on how to define and work with actions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top