2014-01-06 6 views
3

Я пытаюсь отключить JMenu, когда все его подэлементы отключены. У меня есть меню «Добавить новое» и в этом меню два пункта меню: «Файл» и «Каталог».Отключить JMenu, когда все его элементы отключены

Элементы меню привязаны к конкретным действиям, состояние которых я меняю, поэтому пункты меню меняют свое состояние.

Что я пытаюсь добиться, так это то, что меню «Добавить новое» отключается, когда оба действия «Файл» и «Каталог», таким образом, также неактивны.

Я попытался переопределить метод isSelected() 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, как таковой вы можете установить действие для него. Хотя ActionPerformed этого действия никогда не вызывается, его свойства используются для синхронизации соответствующих свойств меню.

Предположим, что все ваши меню управляются (группами) действий, вы можете определить оболочку Action, которая синхронизирует свое включенное состояние с такой группой, а затем установить эту оболочку в меню. Преимущества такого подхода заключаются в том, что вы можете

  • повторное использование такой обертки f.i. если же группировка применяется в MainMenu и всплывающим
  • построения деревьев групп

Обертка может быть что-то вроде:

/** 
* 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

Смежные вопросы