为什么我的ChangeListener仅对JMenu做出反应,而不对JMenuItem做出反应? [英] Why my ChangeListener reacts only for JMenu, and not for JMenuItem?

查看:77
本文介绍了为什么我的ChangeListener仅对JMenu做出反应,而不对JMenuItem做出反应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Now, I have a JMenu, and some JMenuItems in it. I want my program to perform some action when JMenu's and JMenuItem's state is changed to "selected". I don't use MouseLitener's MouseOver, because I want user to be able to navigate in menu using keyboards too. Now, I wrote this listener:

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

When I add this listener to JMenu, it works properly, but when I add it to JMenuItem, nothing happens... When I delete if statement so that listener reacts both, when menu is selected and diselected I works fine for JMenu以及JMenuItem.因此,正如我所看到的,JMenuItem无法通过" isSelected()测试……但是可能会有什么问题呢?:S

When I add this listener to JMenu, it works properly, but when I add it to JMenuItem, nothing happens... When I delete if statement so that listener reacts both, when menu is selected and diselected I works fine for JMenu as well as for JMenuItem. So, as I see, JMenuItem can't "pass" isSelected() test... But what can be a problem? :S

推荐答案

没有任何意图的冒犯,这只是有历史的那些问题之一

No offense intended in any direction, this is just one of those questions with a history

  • 初始要求:当鼠标悬停在JMenuItem上时要做的事情
  • 最初是每个人的宠儿:MouseListener
  • 初始偏离建议(对@mKorbel表示敬意):buttonModel上的ChangeListener,检查过渡属性

  • initial requirement: do-something when a mouse is over JMenuItem
  • initial everybody's darling: MouseListener
  • initial deviating suggestion (kudos to @mKorbel!): ChangeListener on the buttonModel, checking the rollover property

完善的要求:通过键盘和鼠标悬停在JMenuItem刚刚突出显示时执行doSomething.

refined requirement: doSomething when JMenuItem just highlighted, by both keyboard and mouse over.

精确偏差:ActionListener

refined deviation: ActionListener

当前要求:更改JMenu或JMenuItem选定"属性时的操作.

current requirement: doSomething when JMenu or JMenuItem "selected" property changed.

正确而完整的答案(事后看来,因为尚未提及键盘)在第一轮中已经可用:某种语义侦听器足够低级"以捕获状态变化(候选者处于过渡状态),准备好,选中,在buttonModel级别上按下),使menuItem更改其 highlighted 状态.不幸的是,确切的关系尚不为人所知(至少对我而言),没有文档记录(请阅读:懒惰的我很快就找不到任何内容),甚至由于再次总是错误的(对我而言)而令人困惑(对我而言)?对于menuItem

The correct and complete (in hindsight, though, as the keyboard wasn't yet mentioned) answer was available in the first round already: some semantic listener which is "low-level enough" to capture state changes (candidates are rollover, armed, selected, pressed on the buttonModel level) which make the menuItems change their highlighted state. Unfortunately, the exact relation is not well known (to me, at least), undocumented (read: lazy me couldn't find anything on a quick look) and even confusing (again, to me) as rollover is false always (?) for menuItems

实验人员的反应是.. try:下面是一个代码段,它侦听并记录某些菜单树上的状态更改(只需将其扔到任意menuBar中,然后四处移动鼠标并通过键盘进行导航).

The experimentalist's reaction is to .. try: below is a code snippet which listens and logs the state changes on some menu tree (simply throw into an arbitrary menuBar and move the mouse around and navigate by keyboard).

获胜者是:-使用ChangeListener并检查源是否处于选中状态或处于预备状态.

And the winner is: - use a ChangeListener and check if the source is either selected or armed.

    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均可

works for both keyboard and mouse, both JMenu and 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;
}

这篇关于为什么我的ChangeListener仅对JMenu做出反应,而不对JMenuItem做出反应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆