我正在尝试禁用所有子项时禁用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);
}
});
}
答案 0 :(得分:2)
一个容易被遗忘的事实是JMenu 是一个 AbstractButton,因此您可以为它设置一个Action。虽然从未调用Action的actionPerformed,但其属性用于保持菜单的相应属性同步。
因此,假设所有菜单都由(组)Actions驱动,您可以定义一个包装器Action,将其自己的启用状态同步到这样的组,然后将该包装器设置为菜单。这种方法的优点是你可以
包装器可能类似于:
/**
* 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();
}
});