【问题标题】:Why my ChangeListener reacts only for JMenu, and not for JMenuItem?为什么我的 ChangeListener 只对 JMenu 作出反应,而不对 JMenuItem 作出反应?
【发布时间】:2011-08-23 20:26:10
【问题描述】:

现在,我有一个 JMenu,其中还有一些 JMenuItems。我希望我的程序在 JMenu 和 JMenuItem 的状态更改为“已选择”时执行一些操作。我不使用 MouseLitener 的 MouseOver,因为我希望用户也能够使用键盘在菜单中导航。现在,我写了这个监听器:

class MenuItemListener implements ChangeListener {
    @Override
    public void stateChanged(ChangeEvent arg0) {
        JMenuItem item = (JMenuItem) arg0.getSource();
        if(item.isSelected())
            System.out.println(item.getText()+" pressed!");
    }
}

当我将此侦听器添加到jmenu时,它正常工作,但是当我将它添加到jmenuiuem时,没有任何反应...我删除如果侦听器删除侦听器,则选择菜单并丢失时,我为jmenu工作正常工作以及 JMenuItem。所以,正如我所看到的,JMenuItem 不能“通过” isSelected() 测试......但是有什么问题呢? :S

【问题讨论】:

  • 问题的演变(以及从那里链接的问题):stackoverflow.com/questions/5821701/…(只是为了把这个放在眼里,所以不需要重新开始 :-)
  • 仍然认为您应该编辑您的第一个问题以正式包含键盘要求(而不是仅在某些 cmets 中提及) - 可能会立即解决 ;-)

标签: java swing jmenu jmenuitem changelistener


【解决方案1】:

这是预期的多态行为。 JMenuItemisSelected() 方法继承自 AbstractButton,而 Jmenu 中的相同方法被覆盖,因此它“如果当前选择了菜单(突出显示),则返回 true”。

【讨论】:

  • @trashgod 所以从你所说的和@Nika Gamkrelidze 想要什么我认为 OP 应该在 JMenuItems 上设置 Actions 以检测它们何时被选中,对吧?顺便说一句 +1。
  • 这取决于你想做什么以及你想做多少。 JMenu 有一个私有的ChangeListener 调用fireMenuSelected()fireMenuDeselected();你可以覆盖它们,看看会发生什么。
  • @Boro:谢谢! Action 是首选,但菜单不支持 selected 属性。当用户滚动每个JMenuItem 时,我可以看到想要做点什么;我对JMenu 不太乐观。
  • 糟糕,我说得太早了:MenuListener 上的 JMenu 应该可以工作。
  • @Boro 不,在这种情况下,行动不是答案——但如果没有前面的问题,没有人会知道:-)
【解决方案2】:

无意冒犯任何方向,这只是那些有历史的问题之一

  • 初始要求:当鼠标悬停在 JMenuItem 上时做某事
  • 最初大家的宠儿:MouseListener
  • 最初的偏离建议(感谢@mKorbel!):按钮模型上的 ChangeListener,检查翻转属性

  • 细化要求:当 JMenuItem 刚刚突出显示时,通过键盘和鼠标悬停做某事。

  • 精致的宝贝:buttonModel 上的 ChangeListener,未指定属性
  • 细化偏差:ActionListener

  • 当前要求:当 JMenu 或 JMenuItem “selected”属性发生变化时做一些事情。

  • 当前的宝贝:无法通过侦听器完成,覆盖...
  • 当前偏差:Action、MenuListener ...

在第一轮中已经有了正确和完整的答案(尽管事后看来,因为键盘还没有提到):一些语义侦听器“足够低级”以捕获状态变化(候选人是翻转, 武装, 选择, 在 buttonModel 级别上按下) 使 menuItems 改变它们的 highlighted 状态。不幸的是,确切的关系并不为人所知(至少对我而言),没有记录(阅读:懒惰的我无法快速查看任何内容)甚至令人困惑(再次对我而言),因为翻转总是错误的(?)对于菜单项

实验者的反应是.. try: 下面是一个代码 sn-p,它监听并记录某个菜单树上的状态变化(只需放入任意 menuBar 并四处移动鼠标并通过键盘导航)。

获胜者是: - 使用 ChangeListener 并检查源是否被选中或武装。

    ChangeListener ch = new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            if (e.getSource() instanceof JMenuItem) {
                JMenuItem item = (JMenuItem) e.getSource();
                if (item.isSelected() || item.isArmed()) {
                    System.out.println("Highlighted: " + item.getActionCommand());
                }
            }
        }
    };

适用于键盘和鼠标,包括 JMenu 和 JMenuItem

//----------- code snippet to track property changes in menuItem/buttonModel

    // test menu
    JMenu menu = new JMenu("Sample menu");
    menu.setMnemonic('s');
    installListeners(menu);

    // first menuitem
    JMenuItem other = menu.add("content1");
    installListeners(other);
    // second menuitem
    other = menu.add("again + ");
    installListeners(other);

    // sub
    JMenu sub = new JMenu("subMenu");
    installListeners(sub);
    menu.add(sub);

    // menus in sub
    other = sub.add("first in sub");
    installListeners(other);
    other = sub.add("second in sub");
    installListeners(other);

    getJMenuBar().add(menu);

private void installListeners(JMenuItem menu) {
    menu.getModel().addChangeListener(getChangeListener());
    menu.addChangeListener(getChangeListener());
}

private ChangeListener getChangeListener() {
    ChangeListener ch = new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            if (e.getSource() instanceof ButtonModel) {
                ButtonModel model = (ButtonModel) e.getSource();
                System.out.println("from model: " + createStateText(model));
            } else if (e.getSource() instanceof JMenuItem) {
                JMenuItem item = (JMenuItem) e.getSource();
                System.out.println("  from item: " + createStateText(item));
            }
        }

        private String createStateText(ButtonModel model) {
            String text = model.getActionCommand() + " armed: " + model.isArmed();
            text += " selected: " + model.isSelected();
            text += " rollover " + model.isRollover();
            text += " pressed: " + model.isPressed();
            return text;
        }

        private String createStateText(JMenuItem model) {
            String text = model.getActionCommand() + " armed: " + model.isArmed();
            text += " selected: " + model.isSelected();
            // not supported on JMenuItem nor on AbstractButton
           // text += " rollover " + model.isRollover();
           // text += " pressed: " + model.isPressed();
            return text;
        }
    };
    return ch;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-14
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 2021-05-12
    • 2019-09-09
    相关资源
    最近更新 更多