2014-01-06 50 views
3

我试图在禁用其所有子项目时禁用JMenu。 我有一个菜单“添加新的”,在这个菜单中有两个菜单项:“文件”和“目录”。当其所有项目被禁用时禁用JMenu

菜单项绑定到特定的动作,其状态改变,所以菜单项也改变它们的状态。

我想要实现的是当“文件”和“目录”操作以及项目被禁用时,“添加新的”菜单被禁用。

我试图覆盖isSelected()方法od JMenu,它部分工作 - 它不显示项目。但是,菜单仍然被绘制为活动(黑色字体而不是灰色)。

有关如何实现此目的的任何想法?

下面是复制的情况代码示例:

public static void main(String args[]) { 
    java.awt.EventQueue.invokeLater(new Runnable() { 
     public void run() { 

      JFrame frame = new JFrame(); 
      JPopupMenu popup = new JPopupMenu(); 

      final Action actionBeep = new DefaultEditorKit.BeepAction(); 
      final Action actionPaste = new DefaultEditorKit.PasteAction(); 

      JMenu menu = new JMenu("Add"); 
      menu.add(new JMenuItem(actionBeep)); 
      menu.add(new JMenuItem(actionPaste)); 
      popup.add(menu); 

      JTable table = new JTable(3, 3); 

      table.setComponentPopupMenu(popup); 
      table.addMouseListener(new MouseAdapter() { 
       @Override 
       public void mouseReleased(MouseEvent e) { 
        if(e.getClickCount() == 2) { 
         actionBeep.setEnabled(!actionBeep.isEnabled()); 
         actionPaste.setEnabled(!actionPaste.isEnabled()); 
        } 
       } 
      }); 

      frame.add(table); 
      frame.pack(); 
      frame.setVisible(true); 

     } 
    }); 
} 
+1

JMenu有一个setEnabled()函数。为什么不使用它? –

+0

我的设计意味着一些额外的代码,但这当然是一个可行的解决方案。 – Shocked

回答

2

一个容易被人遗忘的事实是,一个JMenu的是,一个 AbstractButton的,因为这样你可以一个动作设置它。虽然该Action的actionPerformed从不被调用,但其属性用于保持菜单的相应属性同步。因此,假设您的所有菜单都是由Actions(groups)驱动的,您可以定义一个包装器Action,将它自己的启用状态同步到这样的组,然后将该包装器设置到菜单中。这种方法的优点是,你可以

  • 重新使用这样一个包装f.i.如果同一类适用于一个主菜单,弹出一个群体
  • 构建树

的包装可能是这样的:

/** 
* Empty Action with enabled state that's the OR'ed enabled of all contained actions. 
*/ 
public static class OrEnabledEmptyAction extends AbstractAction { 

    private List<Action> actions; 

    public OrEnabledEmptyAction(Collection<Action> actions, String name) { 
     super(name); 
     this.actions = new ArrayList<>(actions); 
     installEnabledListener(); 
     updateEnabled(); 
    } 

    /** 
    * Updates this Action's enabled state dependent on enabled of 
    * contained actions. 
    */ 
    private void updateEnabled() { 
     boolean enabled = false; 
     for (Action action : actions) { 
      enabled |= action.isEnabled(); 
     } 
     setEnabled(enabled); 
    } 

    /** 
    * Installs a PropertyChangeListener which updates this Action's 
    * enabled state on notification of enabled of contained actions. 
    */ 
    private void installEnabledListener() { 
     PropertyChangeListener l = new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent evt) { 
       if ("enabled".equals(evt.getPropertyName())) 
        updateEnabled(); 
      } 

     }; 
     for (Action action : actions) { 
      action.addPropertyChangeListener(l); 
     } 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // does nothing, never called for a JMenu anyway 
    } 

} 

它的使用(有附加MAINMENU你的榜样突出重用):

JPopupMenu popup = new JPopupMenu(); 

final Action actionBeep = new DefaultEditorKit.BeepAction(); 
final Action actionPaste = new DefaultEditorKit.PasteAction(); 

final List<Action> actions = new ArrayList<>(); 
actions.add(actionBeep); 
actions.add(actionPaste); 
JMenu menu = new JMenu(); 
// add actions to menu in popup 
for (Action action : actions) { 
    menu.add(action); 
} 
// sets the menu's action to the OR-Enabled 
menu.setAction(new OrEnabledEmptyAction(actions, "Add")); 
popup.add(menu); 

JMenuBar bar = new JMenuBar(); 
JMenu mainMenu = new JMenu(); 
// add actions to menu in menuBar 
for (Action action : actions) { 
    mainMenu.add(action); 
} 
// re-use or-action 
mainMenu.setAction(menu.getAction()); 
bar.add(mainMenu); 
frame.setJMenuBar(bar); 

JTable table = new JTable(3, 3); 

table.setComponentPopupMenu(popup); 
// for seeing the effect, change enabled state of only one action 
// per released 
table.addMouseListener(new MouseAdapter() { 
    int index; 
    @Override 
    public void mouseReleased(MouseEvent e) { 
     if (!SwingUtilities.isLeftMouseButton(e)) 
      return; 
     actions.get(index).setEnabled(!actions.get(index).isEnabled()); 
     index = (index +1) % actions.size(); 
    } 
}); 
+0

是的!这很棒。我的设计基于行动,这完全适合它。谢谢! – Shocked

相关问题