2011-05-12 36 views
4

现在,我有一个JMenu和其中的一些JMenuItems。当JMenu和JMenuItem的状态改变为“selected”时,我希望我的程序执行一些操作。我不使用MouseLitener的MouseOver,因为我希望用户能够使用键盘在菜单中进行导航。现在,我写了这个监听器:为什么我的ChangeListener只对JMenu作出反应,而不是对JMenuItem作出反应?

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的,它工作正常,但是当我把它添加到JMenuItem,但是什么也没有发生。当我使听者反应都删除if语句,当菜单被选中和被选中时,我对JMenu以及JMenuItem都可以正常工作。所以,正如我所看到的,JMenuItem不能“通过”isSelected()测试......但是有什么问题呢? :S

+0

进化的问题(和一个从那里的链接):http://stackoverflow.com/questions/5821701/what- listener-should-i-use-java(只是为了让这个角度来看,所以不需要重新开始:-) – kleopatra 2011-05-12 07:39:56

+1

仍然认为你应该编辑你的第一个问题,正式包含键盘要求(而不是只是在一些评论中提到) - 可能会立即解决;-) – kleopatra 2011-05-12 10:48:08

回答

6

没有违法意图在任何方向,这仅仅是一个历史的问题之一

  • 最初的要求:做某事时,鼠标悬停的JMenuItem
  • 最初大家的宠儿:MouseListener的
  • 初始偏差建议(ko @ to @mKorbel!):ChangeListener on buttonModel,检查翻滚属性

  • 精修要求:doSomething when JMenuI只是通过键盘和鼠标突出显示。

  • 精制宠儿:在ButtonModel的的ChangeListener,未指定的属性
  • 精制偏差:ActionListener的

  • 电流需求:doSomething的 “选择” 或JMenu的JMenuItem的时改变性质。

  • 当前的宠儿:不能用监听器,超控来完成...
  • 电流偏差:动作,MenuListener ...

正确和完整的(事后证明,不过,作为键盘还没有提到)答案已经在第一轮中可用:一些语义监听器是“足够低级”的捕获状态变化(候选者是滚动,武装,选中,按下buttonModel级别),这使得menuItems改变他们突出显示状态。不幸的是,确切的关系并不为人所知(至少对我来说),没有证据(读:懒惰我无法快速查找任何东西),甚至令人困惑(再次,对我来说),因为翻转始终是错误的(?) for menuItems

实验者的反应是......试试:下面是一个代码片断,它监听并记录某些菜单树上的状态更改(只需将其放入任意菜单栏并移动鼠标并通过键盘进行导航)即可。

获胜者是: - 使用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; 
} 
+1

+1由匿名选举人 – mKorbel 2011-05-12 11:33:30

+0

+1为装备精良! :-) – trashgod 2011-05-12 12:37:42

4

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

+0

所以,我能做些什么? :S – nicks 2011-05-12 06:27:37

+2

@trashgod所以从你在说什么和@尼卡Gamkrelidze希望我认为OP应该设置操作JMenuItems来检测它们何时被选中,对吧? BTW +1。 – Boro 2011-05-12 06:30:35

+0

这取决于你想要做什么以及你想做多少。 'JMenu'有一个私人'ChangeListener',可以调用'fireMenuSelected()'和'fireMenuDeselected()';你可以覆盖他们,看看发生了什么。 – trashgod 2011-05-12 06:56:38