2012-01-18 4 views
3

참고 : 내 질문을 완전히 이해하려면 예제를 컴파일하고 실행해야 할 수도 있습니다. 이것이 유대인이 아니라면, 나는 사전에 사과한다.자바 팝업 버튼

JToggleButtonJPopupMenu을 기반으로하는 스윙 컨트롤을 만들려고합니다.

팝업 메뉴가 표시되면 토글 버튼이 선택되고 팝업 메뉴가 표시되지 않으면 토글 버튼이 선택 취소됩니다. 따라서 팝업은 임의의 구성 요소를 포함 할 수 있다는 것을 제외하고는 동작이 JComboBox과 유사합니다.

다음 코드는 컨트롤 (예 : JPopupToggleButton과 같은 자체 클래스에있을 것입니다.)을 만드는 방법의 예입니다. 불행히도, 다른 모양과 느낌으로 다른 동작을 보입니다 (필자는 Metal과 Nimbus로 테스트했습니다).

여기에 게시 된 코드는 Nimbus가 아니라 Metal에서 예상대로 작동합니다. Nimbus를 사용할 때 토글 버튼을 반복적으로 클릭하여 팝업을 표시하거나 숨기면 무슨 뜻인지 알 수 있습니다.

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.MouseInfo; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 
import javax.swing.event.PopupMenuEvent; 
import javax.swing.event.PopupMenuListener; 

public class PopupButtonExample extends JFrame 
{ 
    public static void main(String[] args) 
    { 
     java.awt.EventQueue.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       PopupButtonExample example = new PopupButtonExample(); 
       example.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       example.setVisible(true); 
      } 
     }); 
    } 

    public PopupButtonExample() 
    { 
     super("Components in Popup"); 

     JPanel popupPanel = new JPanel(); 
     popupPanel.setLayout(new BorderLayout()); 
     popupPanel.add(new JLabel("This popup has components"), 
       BorderLayout.NORTH); 
     popupPanel.add(new JTextArea("Some text", 15, 20), 
       BorderLayout.CENTER); 
     popupPanel.add(new JSlider(), BorderLayout.SOUTH); 

     final JPopupMenu popupMenu = new JPopupMenu(); 
     popupMenu.add(popupPanel); 

     final JToggleButton popupButton = new JToggleButton("Show Popup"); 
     popupButton.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       if(popupButton.isSelected()) 
        popupMenu.show(popupButton, 0, popupButton.getHeight()); 
      } 
     }); 

     popupMenu.addPopupMenuListener(new PopupMenuListener() 
     { 
      @Override 
      public void popupMenuWillBecomeVisible(PopupMenuEvent pme) {} 

      @Override 
      public void popupMenuCanceled(PopupMenuEvent pme) {} 

      @Override 
      public void popupMenuWillBecomeInvisible(PopupMenuEvent pme) { 
       Point mouseLoc = MouseInfo.getPointerInfo().getLocation(); 
       Point componentLoc = popupButton.getLocationOnScreen(); 
       mouseLoc.x -= componentLoc.x; 
       mouseLoc.y -= componentLoc.y; 
       if(!popupButton.contains(mouseLoc)) 
        popupButton.setSelected(false); 
      } 
     }); 

     JPanel toolBarPanel = new JPanel(); 
     toolBarPanel.add(popupButton); 
     JToolBar toolBar = new JToolBar(); 
     toolBar.add(toolBarPanel); 

     setLayout(new BorderLayout()); 
     add(toolBar, BorderLayout.PAGE_START); 
     setPreferredSize(new Dimension(640, 480)); 
     pack(); 
    } 
} 

다음 줄을 출력하면 Nimbus에서는 코드가 예상대로 작동하지만 Metal에서는 예상대로 작동하지 않습니다. 다시 말하지만 토글 버튼을 계속 클릭하여 내 뜻을 확인하십시오. 그래서 여기

//    Point mouseLoc = MouseInfo.getPointerInfo().getLocation(); 
//    Point componentLoc = popupButton.getLocationOnScreen(); 
//    mouseLoc.x -= componentLoc.x; 
//    mouseLoc.y -= componentLoc.y; 
//    if(!popupButton.contains(mouseLoc)) 

내 두 가지 질문은 다음과 같습니다

(1) 후광에서, 이유는 무엇입니까는 금속과 마찬가지로, 토글 버튼에 전달되지 팝업 패널을 숨 깁니다 클릭?

(2) 모든 모양과 느낌에서 작동하도록이 문제를 해결하려면 어떻게해야합니까?

+2

일을 좋은 상담자 JWindow의에 대한 – mKorbel

답변

0

몇 가지 조사를 한 후 Nimbus와 Metal의 차이점을 발견했습니다. 팝업을 닫을 때 다음 플래그는 이벤트의 소비를 제어하는 ​​(적어도 BasicPopupMenuUI에 의해) 사용됩니다

UIManager.getBoolean("PopupMenu.consumeEventOnClose"); 

후광을 사용하여,이 true를 반환합니다. Metal을 사용하면 false을 반환합니다. 따라서 다음과 같이 정의한다 popupMenuWillBecomeInvisible 방법은 다음과 같습니다

if(UIManager.getBoolean("PopupMenu.consumeEventOnClose")) 
{ 
    popupButton.setSelected(false); 
} 
else 
{ 
    Point mouseLoc = MouseInfo.getPointerInfo().getLocation(); 
    Point componentLoc = popupButton.getLocationOnScreen(); 
    mouseLoc.x -= componentLoc.x; 
    mouseLoc.y -= componentLoc.y; 
    if(!popupButton.contains(mouseLoc)) 
    { 
     popupButton.setSelected(false); 
    } 
} 
4
  • 는 후광 (그리고 개발 중간에 어딘가 종료) 나는 금속

  • 모든 표준 L & F와 비교 당신이 자신의 특정 문제를 가지고 한 JToggleButton에 세 마우스 클릭이 필요하다고보고 너무 버그가 , 특히 SystemLookAndFeel

  • JPopup에는 JWindow가 사용됩니다. JPopup에는 또 다른 버그가 있으므로 JPopup with JCombobox

+1

+1로, http://sscce.org/을 게시. 그런 다음 'WindowListener'를 사용하고 windowDeactivated() 이벤트를 처리하여 창을 숨기고 토글 버튼을 재설정 할 수 있습니다. – camickr

+0

응답 해 주셔서 감사합니다. 오라클이 Nimbus를 javax.swing으로 이동시킨 것은 이상한 것 같습니다.JDK 7을 사용하여 절반 만 개발 한 다음 중단하면 JDK 7과 함께 plaf 패키지가 실행됩니다. Popup 대신 JWindow를 사용하는 것에 관해서는 Popup/JPopupMenu로 사람들이 겪었던 문제점에 대해 궁금합니다. 항상 저에게 잘 돌아간 것처럼 보이지만, 오랫동안 Swing을 사용하지 않았습니다. – lifelongcoug