使用TextAction实现带有actionPerformed的JMenu

时间:2014-09-16 08:30:33

标签: java swing awt jmenu

我有一个带有多个JTextArea的Java Swing界面,我正在实现一个"编辑"具有各种不同功能的菜单,例如"查找","复制","粘贴"等。当我点击JMenuItem时我需要知道哪个JTextArea有一个焦点可以通过TextAction实现(我没有沿着FocusListener的路线走下去并跟踪最后的焦点:

JMenuItem miFind = new JMenuItem(new EditHandler("Find"));

class EditHandler extends TextAction {
  private String s = null;

  public EditHandler(String vs) {
    super(vs);
    s = vs;
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    JTextComponent c = getFocusedComponent();
    if (s.equals("Find")) {
      showFindDialog(c);
    }
  }
}

这很好但很好,但我希望能够禁用"查找" JMenuItem在某些情况下(例如,如果特定的JTextArea被停用或为空。我可以在ActionListener上实施JMenu但我无法使用{{} 1}}以确定getFocusedComponent()具有焦点的内容。

根据Java文档,JTextArea构造函数采用JMenu(如Action),我尝试了以下内容:

JMenuItem

但是,虽然构造函数会触发,mEdit = new JMenu(new EditHandler("Edit")); 事件不会在actionPerformed() EditHandler内触发JMenu。如果我可以解雇它,那么我打算启用或禁用我的"查找" JMenuItem

2 个答案:

答案 0 :(得分:1)

最好的方法是使用文本组件的动作映射来放置相应的动作。在这种情况下,您可以为某些文本组件禁用它。

@Override
public void actionPerformed(ActionEvent e) {
  JTextComponent c = getFocusedComponent();
  if (s.equals("Find")) {
    Action a = c.getActionMap().get("Find");
    if (a.isEnabled()) {
      // generate new event to modify the source (menu item -> text component)
      ActionEvent ae = new ActionEvent(c, e.getID(), e.getCommand());
      a.actionPerformed(ae);
    }
  }
}

对于每个文本组件,您必须提供操作并使用组件的操作映射进行注册。

public class UniversalFindAction extends AbstractAction {
  public void actionPerformed(ActionEvent ae) {
    JTextComponent c = (JTextComponent) ae.getSource();
    showFindDialog(c);
  }
}

// registering of action
JTextComponent comp = new JTextArea();
comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK), "Find");
comp.getActionMap().put("Find", new UniversalFindAction());

答案 1 :(得分:1)

感谢@ sergiy-medvynskyy我已经实施了一个全球焦点监听器来跟踪最后的JTextArea

KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() {
  @Override
  public void propertyChange(final PropertyChangeEvent e) {
    if (e.getNewValue() instanceof JTextArea) {
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          tFocused = (JTextArea)e.getNewValue();
        }
      });
    }
  }
});

然后,我使用tFocused上的MenuListener检查JMenu对象,以验证JTextArea当前具有焦点的内容。然后,我可以根据具体情况在setEnabled()上调用JMenuItem