如何动态构建JMenu(而不仅仅是运行时创建)?

时间:2018-07-14 00:16:24

标签: java swing dynamic jmenu jmenuitem

要清楚地是,这里出现的几个类似的条目实际上并没有谈论动态地构建菜单,因为它们的所有对象名称选择以及诸如此类的代码都已作为源代码中已写入的固定字符串出现在了代码中。他们所做的只是等到运行时创建其静态设计的菜单项。我发现有两个条目是这样的:OneTwo.那里所关心的只是刷新显示的琐碎(但至关重要)的任务,而不是像实际动态创建内容那样。

与之形成鲜明对比的是,我要做的是真正地动态添加:我希望用户能够选择将项目添加到子菜单中,然后他们可以在以后选择并在应用程序中采取行动。

让我们简单地将一个整数值添加到菜单中,然后以后再选择它,就像使用组合框轻松完成但通过菜单轻松完成一样。

问题不是与定义有关的语法,例如,MenuListener指向一种知道如何操作的方法,这不是问题。相反,我只是对动态NAMING SPACE以及如何“取消引用”字符串(例如,作为对象名称)了解得不够多。坦率地说,我该如何动态命名我没想到要创建的新对象(不是实物而是数量)? IOW,我该如何巧妙地构造一个实际上包含要运行的代码的字符串,然后要求Java运行它? Java的语法是什么?也许可以将问题简化为对象名称。说,这个名字是我可以构造的字符串。如何在我的JMenuItem声明中使用它? ...我知道如何在BASH中执行此操作,但是如何在Java中执行此操作?

(我希望不必将其创建为文件,进行编译,并以某种方式将类文件附加到正在运行的程序中,然后运行它-DAMN会很麻烦!)

谢谢。

1 个答案:

答案 0 :(得分:1)

如果我理解您的总体意图,那么我建议从Actions API开始,该{{3}}用于创建独立的工作单元,这些工作单元与它们的显示方式无关。

这使您可以定义可重用(或动态情况下)的操作,这些操作可以通过菜单,工具栏,按钮甚至键绑定立即执行。

因为设置Action可能有点乏味,所以我可能考虑使用构建器模式,但是您不必这样做,可以根据需要手动构建它们;)

public class ActionBuilder {
    private ActioBuilderAction action;

    public ActionBuilder() {
        action = new ActionBuilder.ActioBuilderAction();
    }

    public ActionBuilder toolTip(String text) {
        action.putValue(Action.SHORT_DESCRIPTION, text);
        return this;
    }

    public ActionBuilder command(String text) {
        action.putValue(Action.ACTION_COMMAND_KEY, text);
        return this;
    }

    public ActionBuilder mnemonic(int key) {
        action.putValue(Action.MNEMONIC_KEY, key);
        return this;
    }

    public ActionBuilder displayedMnemonicIndex(int index) {
        action.putValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY, index);
        return this;
    }

    public ActionBuilder text(String text) {
        action.putValue(Action.NAME, text);
        return this;
    }

    public ActionBuilder smallIcon(Icon icon) {
        action.putValue(Action.SMALL_ICON, icon);
        return this;
    }

    public ActionBuilder largeIcon(Icon icon) {
        action.putValue(Action.LARGE_ICON_KEY, icon);
        return this;
    }

    public ActionBuilder acceleratorKey(KeyStroke ks) {
        action.putValue(Action.ACCELERATOR_KEY, ks);
        return this;
    }

    public ActionBuilder actionListener(ActionListener listener) {
        action.setListener(listener);
    }

    public Action build() {
        return action;
    }

    public class ActioBuilderAction extends AbstractAction {

        private ActionListener listener;

        public void setListener(ActionListener listener) {
            this.listener = listener;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (listener != null) {
                listener.actionPerformed(e);
            }
        }

    }
}

然后,您可以简单地建立一个新菜单,例如...

Action action = new ActionBuilder().text("Super awesome command").actionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Super aweseom comand GO!");
    }
}).build();

JMenuItem mi = new JMenuItem(action);

现在,我想您可能会拥有某种“命令执行器”类。实际执行命令。我将创建一个实现ActionListener的桥接类,并在调用该类时执行指定的命令

public class CommandListener implements ActionListener {
    private String command;

    public CommandListener(String command) {
        this.command = command;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        CommandExecutor executor = new CommandExecutor();
        executor.execute(command)
    }


}

然后可以在第一个示例中使用它代替ActionListener ...

Action action = new ActionBuilder().text(commandName).actionListener(new CommandListener(command)).build();

总体思路