【问题标题】:JAVA declaring uninitialized JMenuItem() items inside JMenuItem[] constructorJAVA 在 JMenuItem[] 构造函数中声明未初始化的 JMenuItem() 项
【发布时间】:2019-09-17 09:14:38
【问题描述】:

我有这个代码:

JMenuItem itemA;
JMenuItem itemB;
JMenuItem itemC;
JMenuItem[] items = {itemA, itemB, itemC};

我想做的是在 JMenuItem 数组构造函数中声明那些 JMenuItem,这样我就可以省去几行其他不必要的代码(即首先摆脱对这些单独项目的初始声明)。我希望在这个虚构的代码中有所体现:

JMenuItem[] items = {JMenuItem itemA, JMenuItem itemB, JMenuItem itemC};

...但这当然行不通。谁能告诉我该怎么做,好吗? 顺便说一句,这些项目稍后会在代码中初始化。

【问题讨论】:

  • @Abra 你读过我说它们稍后在代码中初始化的地方吗?所以是的,这就是我想要的。

标签: java arrays swing jmenuitem


【解决方案1】:

没有必要为了声明变量而声明变量 - 将它们声明为尽可能靠近它们的使用位置。由于您没有将items 的可见性设置为private 或类似的,我假设您的代码存在于一个方法中,可能是一个窗口的构造函数。在这种情况下,我建议使用RAII 的(精神):在同一语句中进行初始化和声明。我的代码看起来像

JMenuItem[] items = {
    new JMenuItem(openFileAction),
    new JMenuItem(saveFileAction),
    new JMenuItem(exitApplicationAction)
};

这假设您使用Action 的子类,或者更好的是AbstractAction 来为每个项目提供标签、快捷方式、名称、图标和actionPerformed 代码。动作的优点是它们的名称比itemA 更容易记住,它们可以在多个地方调用(和显示)(作为按钮、作为项目、在多种类型的菜单中),并且可以在所有这些都取决于应用程序的状态(例如,当没有要保存的文件时,saveFileAction 可以在任何地方禁用)。

实际上,我会更进一步。由于菜单创建后很少需要更改,并且您可以访问其内部操作来启用/禁用它们,因此您可以完全跳过声明 items

JMenu fileMenu = new JMenu("File");
fileMenu.add(new JMenuItem(openFileAction));
// ... 

编辑关于如何定义“一次完成所有事情”:

对于 JMenuItems,我更喜欢使用 Actions,因为 Actions 更灵活(因为它们可以在多个地方使用)。您可以在一次调用中为操作提供标签及其代码,这类似于您可以使用 JMenuItems 执行的操作:

Action exitApplicationAction = new AbstractAction("Exit application") {
    public void actionPerformed(ActionEvent ae) {
      System.exit(0);
    }
};

但是,拥有 AbstractAction 的自制子类(此处称为 AllInOneAction)允许以最少的样板文件一次设置 所有内容(请注意,它比上面的例子!):

Action exitApplicationAction = new AllInOneAction(
   "Exit application", "exit.png", "Exit the program",
   KeyEvent.VK_E, "control shift E", () -> System.exit(0));

在该子类内部,您可以设置一组操作键:

public AllInOneAction(Object name, String iconName, String tooltip,
        Integer mnemonic, String accelerator, Runnable callback) {
    super("" + name); // allows your name to be an enum, useful for lookup
    putValue(Action.SHORT_DESCRIPTION, tooltip);
    putValue(Action.MNEMONIC_KEY, mnemonic);
    putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(accelerator));
    BufferedImage icon = loadImage(iconName); 
    BufferedImage small = scaleImage(icon, 16, 16);   
    putValue(Action.LARGE_ICON_KEY, new ImageIcon(icon));
    putValue(Action.SMALL_ICON, new ImageIcon(small));
    this.callback = callback;
}

请注意,loadImagescaleImage 的实现留作练习,但这对于“如何填充我的 JMenu”的原始问题已经足够大了。

【讨论】:

  • 好点。实际上,不需要所有 JMenuItem 的变量,而是可以通过那里的 Action 禁用和隐藏和重新标记此类菜单项。
  • 如果像您写的fileMenu.add(new JMenuItem(openFileAction)); 那样定义,我们可以在“一次性”中定义项目属性(actionListener,setName)吗?我想像fileMenu.add(new JMenuItem(){setName("some name");}); 这样的东西 - 甚至可能吗?跨度>
  • 如此简短的回答将是“不,我问的方式是不可能的”,遗憾的是。但是感谢扩展您的答案,但这不是我想要的,因为它在将代码简化为fileMenu.add(openItem = new JMenuItem(MAINMENU_FILE_OPEN)); openItem.addActionListener((ActionEvent e) -> {...}); 之类的正常方式方面基本上没有区别。此外,您的代码实际上似乎比这种“简单”的方法复杂得多。
  • 如果您绝对必须使用 JMenuItem(而不是直接使用 Action),这可行:fileMenu.add(new JMenuItem(new AbstractAction("some name") {public void actionPerformed(ActionEvent ae) {System.exit(0);}}));
  • 是的!这很好用 - 非常感谢你(如果这是我的问题的优点,你肯定会收到“正确答案”标志)......所以至少我点击向上箭头,因为你的答案很有用 - 也许你甚至可以把它放在你帖子的最后,让其他人很容易找到它!
【解决方案2】:

替换这个

JMenuItem[] items = {JMenuItem itemA, JMenuItem itemB, JMenuItem itemC};

有了这个

JMenuItem[] items = {null, null, null}; //option 1
JMenuItem[] items = new JMenuItem[3]; //option 2

【讨论】:

    【解决方案3】:

    你可以这样初始化数组:

    JMenuItem[] items = {new JMenuItem(), new JMenuItem(), new JMenuItem()};
    

    然后使用 items[0], items[1], items[2] 代替 itemA, itemB, itemC。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-24
      • 1970-01-01
      • 2018-08-02
      • 2013-02-10
      相关资源
      最近更新 更多