2013-03-14 31 views
0

我注意到,一旦我的JPopupMenu第一次變得可見,它的MenuItems不會反映他們對下一個可見性所做的更改。這是代碼;JPopupMenu的MenuItems無法響應更改...爲什麼?

private static void addListener(final JPopupMenu popup, final String someLetter) 
{ 
    popup.addPopupMenuListener(new PopupMenuListener(){    
     @Override 
     public void popupMenuWillBecomeVisible(PopupMenuEvent evt) 
     { 
      JMenuItem menuItem3 = (JMenuItem)popup.getComponent(3); 
      String[] letters = {"A", "B", "C", "D"}; 
      ArrayList<String> lettersList = new ArrayList<String>(); 
      lettersList.addAll(Arrays.asList(letters)); 
      if(lettersList.contains(someLetter)){ 
       menuItem3.setEnabled(true); 
      } 
      else{ 
       menuItem3.setEnabled(false); 
      } 
     } 
    }); 
} 

通常我會期待popupMenuWillBecomeVisible下的線路將始終執行每當popupMenu越來越彈起。但令我驚訝的是,它只在第一次工作,隨後不測試指定的條件來啓用或禁用menuItem3。請讓別人幫助兄弟!

+0

請問什麼'lettersList',爲了更好的幫助,儘快發佈[SSCCE](http://sscce.org/),短的可運行的,可編譯的,只是添加了'JPopup'的'JFrame',僅包含'lettersList' – mKorbel 2013-03-14 18:59:10

+0

'lettersList'只是一個從'letters'數組創建的字符串ArrayList(參見代碼行7),使我能夠檢查(僅在2行)參數'letter'是否是Array的元素之一' letters'。只是不想做一步一步的迭代。 – CodeBurner 2013-03-14 19:20:25

+0

我迷路了,也許有1K的變化,簡單的從這個線程沒有在你身邊的SSCCE – mKorbel 2013-03-14 19:22:03

回答

1

這似乎對我很好。看看下面這5顯示的菜單項中切換它們「enability」每次這個例子中你執行一個右鍵:爲推動我在這個過程中,試圖寫一個SSCCE COS

import java.awt.event.ActionEvent; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.AbstractAction; 
import javax.swing.JFrame; 
import javax.swing.JMenuItem; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JPopupMenu; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.PopupMenuEvent; 
import javax.swing.event.PopupMenuListener; 

public class TestPopupMenu { 

    private void initUI() { 
     final JFrame frame = new JFrame(TestPopupMenu.class.getSimpleName()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JPanel panel = new JPanel(); 
     final JPopupMenu popup = new JPopupMenu(); 
     final List<JMenuItem> items = new ArrayList<JMenuItem>(); 
     for (int i = 0; i < 5; i++) { 
      JMenuItem item = new JMenuItem(new AbstractAction("Action " + (i + 1)) { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        JOptionPane.showMessageDialog(popup, getValue(NAME) + " has been clicked"); 
       } 
      }); 
      item.setEnabled(i % 2 == 0); 
      items.add(item); 
      popup.add(item); 
     } 
     popup.addPopupMenuListener(new PopupMenuListener() { 

      @Override 
      public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 
       for (JMenuItem item : items) { 
        item.setEnabled(!item.isEnabled()); 
       } 
      } 

      @Override 
      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 

      } 

      @Override 
      public void popupMenuCanceled(PopupMenuEvent e) { 

      } 
     }); 
     panel.setComponentPopupMenu(popup); 
     frame.add(panel); 
     frame.setSize(300, 200); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (ClassNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InstantiationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (UnsupportedLookAndFeelException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new TestPopupMenu().initUI(); 
      } 
     }); 
    } 
} 
+0

+1這個@Guillaume Polet。很好的指導。太糟糕了,我的名聲不能投你的答案。 – CodeBurner 2013-03-15 01:46:39

1

感謝@mKorbel,我找到了解決方案。無論如何,這是我的SSCCE,它可能對其他人有用。誰知道?只需複製並運行即可瞭解其工作原理。

(注:該代碼是不是真的很短,但因爲次要問題,我打算以後這姿勢)

import java.awt.Dimension; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JMenuItem; 
import javax.swing.JPopupMenu; 
import java.util.ArrayList; 
import java.util.Arrays; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.PopupMenuEvent; 
import javax.swing.event.PopupMenuListener; 

public class CustomPopup extends JPopupMenu 
{ 
    private JMenuItem menuItem1 = new JMenuItem("One"); 
    private JMenuItem menuItem2 = new JMenuItem("Two"); 
    private JMenuItem menuItem3 = new JMenuItem("Three"); 
    private JMenuItem menuItem4 = new JMenuItem("Four"); 
    private JMenuItem menuItem5 = new JMenuItem("Five"); 

    public CustomPopup() 
    { 
     this.add(menuItem1); 
     this.add(menuItem2); 
     this.add(menuItem3); 
     this.add(menuItem4); 
     this.add(menuItem5); 
     addListeners(this); 
    } 

    private void addListeners(final JPopupMenu popup /*, final String someLetter*/) 
    { 
     popup.addPopupMenuListener(new PopupMenuListener(){    
      @Override 
      public void popupMenuWillBecomeVisible(PopupMenuEvent evt) 
      { 
       JMenuItem menuItem = (JMenuItem)popup.getComponent(3); 
       String[] letters = {"A", "B", "C", "D"}; 
       ArrayList<String> lettersList = new ArrayList<String>(); 
       lettersList.addAll(Arrays.asList(letters)); 
       String someLetter = getRandomAlphabet(); 
       if(lettersList.contains(someLetter)){ 
        menuItem.setEnabled(true); 
       } 
       else{ 
        menuItem.setEnabled(false); 
       } 
      } 
      @Override 
      public void popupMenuWillBecomeInvisible(PopupMenuEvent evt){ 
       // No Override 
      } 

      @Override 
      public void popupMenuCanceled(PopupMenuEvent evt){ 
       // No Override 
      } 
     }); 
    } 

    private String getRandomAlphabet() 
    { 
     String alpha = ""; 
     String Alphas[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}; 
     double bigNum = Math.random() * 1000000; 
     String str = String.valueOf(bigNum); 
     int idx = Integer.valueOf(String.valueOf(str.charAt(str.length() - 1))); 
     if(idx < 6) 
     { 
      alpha = Alphas[idx]; 
     } 
     else 
     { 
      alpha = Alphas[idx - 5]; 
     } 
     return alpha; 
    } 

    public static void main(String[] args) 
    { 
     /*try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (ClassNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InstantiationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (UnsupportedLookAndFeelException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     }*/ 

     JPanel panel = new JPanel(); 
     JPopupMenu popupMenu = new CustomPopup(); 
     panel.setComponentPopupMenu(popupMenu); 
     panel.setLayout(new GridBagLayout()); 

     /*JButton button = new JButton("Action"); 
     button.setSize(new Dimension(60, 20)); 
     button.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       JOptionPane.showMessageDialog(null, "Button was clicked"); 
      } 
     }); 
     panel.add(button);*/ 

     JFrame frame = new JFrame("popupTest"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(new Dimension(200, 200)); 
     frame.add(panel); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 

的問題:現在這個做什麼,我想要它做的,(即啓用和禁用menuItem4動態基於某些指定計算的隨機結果getRandomAlphabet()),我看了@Guillaume Polet的Lovely實現並對其進行了測試。非常好...所以我只是決定添加一個按鈕,並測試我使用UIManager這不是Native Java Default時出現的彈出窗口中最令人討厭的問題之一......並且發生同樣的事情!

我的意思是?當LnF不是默認Metal時,在彈出菜單顯示後單擊任何其他可操作組件上的popupMenu的外部在第一次單擊時不起作用(這隻會將彈出框設置爲不可見)。然後你必須再次點擊組件(第二次)才能觸發它的Action ...非常討厭它了嗎?

想要了解這種情況,只需取消上述代碼的UIManager部分(我從@Guillaume Polet的美麗解決方案中取得了該部分)並取消註釋我添加的Button部分,然後運行該程序並查看在發生什麼情況時您在顯示popupMenu後立即嘗試單擊該按鈕。有趣的是,這個問題不會發生,當使用Java的默認金屬LnF

我已經與Windows 7系統默認外觀和感覺作戰這個問題無濟於事,所以我決定讓睡覺的狗謊言......但說實話,我認爲這件事有一個解決辦法......我知道肯定有人對這件事情有所斬獲......解決這個問題的代碼塊,方向,鏈接,任何地方都會讓我非常高興。感謝好人!

+0

你是否談論Java7在Win7/8 – mKorbel 2013-03-15 08:02:35

+0

@mKorbel不,不是Java7!...我的意思是「Win7」,所以我只是說這是我注意到bcos的行爲我正在使用Win7操作系統。 – CodeBurner 2013-03-16 08:41:51

+0

[看看是否使用此代碼引起的,嘗試應用代碼](http://stackoverflow.com/q/7423533/714968) – mKorbel 2013-03-16 10:07:46

相關問題