2011-05-12 51 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