2013-03-14 5 views
0

제 JPopupMenu가 처음으로 표시되면 해당 MenuItem에는 다음 가시성을 위해 변경된 내용이 반영되지 않습니다. 다음은 코드입니다.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

제발 더 나은 도움을 위해 [SSCCE] (http://sscce.org/), 짧은 실행 파일, 컴파일 가능한,'JFrame'에'JPopup'이 추가되었고'lettersList' 만 포함되었습니다 – mKorbel

+0

'lettersList'는'letters' 배열에서 생성 된 String ArrayList입니다 (코드 라인 7 참조).'letter' 인자가 배열의 원소 중 하나인지' 편지'. 방금 단계 반복으로 단계를 수행하고 싶지 않았습니다. – CodeBurner

+0

나는 길을 잃었습니다. 어쩌면 1K 개의 변형이있을 수 있습니다.이 스레드에서 SSCCE가 없으면 간단합니다. – mKorbel

답변

1

이것은 나를 위해 아주 잘 작동하는 것 같습니다. 5 개 메뉴 항목을 표시하고 그들의 "enability"매번 전환하는 아래의 예를 확인하면 마우스 오른쪽 버튼을 클릭 수행하는 과정에서 SSCCE의 COS를 시도하고 작성하는 나를 밀어 위해 @mKorbel에

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 @ 여기가 Polet입니다. 좋은 가이드. 너무 나쁜 내 명성은 귀하의 답변을 투표 수 없습니다. – CodeBurner

1

감사합니다, I 해결책을 찾았습니다. 어쨌든 내 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); 
    } 
} 

질문 지정된 계산 getRandomAlphabet()의 무작위 결과를 바탕으로 menuItem4을 동적으로 비활성화하십시오. @Guillaume Polet의 Lovely 구현을 살펴본 후 테스트했습니다. 아주 좋아 ... 그래서 방금 버튼을 추가하기로 결정했고 기본 자바 기본이 아닌 UIManager을 사용할 때 팝업을 가지고 있었던 가장 성가신 문제 중 하나를 테스트했습니다. 똑같은 일이 발생합니다!

의미는 무엇입니까? LnF가 기본값 Metal이 아닌 경우 popupMenu가 표시된 후에 다른 Actionable 구성 요소에서 popupMenu 외부를 클릭하면 첫 번째 클릭에서 작동하지 않습니다 (팝업 만 보이게 설정 됨). 그런 다음 해당 액션이 해고되기 전에 구성 요소를 다시 클릭해야합니다 (두 번째) ... 매우 성가신 일이 아닙니까?

이 시나리오의 느낌을 얻으려면 위의 코드 UIManager 섹션의 주석 처리를 제거하고 (@Guillaume Polet의 아름다운 솔루션에서 가져온 것) 또한 추가 한 Button 섹션의 주석 처리를 제거한 다음 프로그램을 실행하고 popupMenu이 표시된 직후 버튼을 클릭하십시오. 재미있는 점은 자바의 기본 메탈 LnF를 사용할 때이 문제가 발생하지 않는다는 것입니다.

Windows 7의 시스템 기본 룩앤필을 사용하여이 문제를 해결했지만 잠자는 개가 거짓말을하기로 결정했습니다.하지만 솔직히 저는 이 문제를 해결할 수있는 방법이 있다고 생각합니다.이 문제를 해결할 수있는 사람이 있어야한다는 것을 알고 있습니다. 코드 블록, 길 찾기, 링크, 기타,이 문제를 해결할 수있는 곳이면 내 기쁨이 될 것입니다. 좋은 사람들에게 감사드립니다!

+0

Win7/8에서 Java7에 대해 이야기 하시겠습니까? – mKorbel

+0

@mKorbel 아니요, Java7이 아닙니다! ... "Win7"을 의미했기 때문에 Win7 OS를 사용하고있는 것으로 보았습니다. – CodeBurner

+0

[이 코드로 인해 발생하는 경우 응답에서 코드 적용 시도] 참조 (http://stackoverflow.com/q/7423533/714968) – mKorbel