2012-01-18 15 views
3

注:私の質問を完全に理解するために私の例をコンパイルして実行する必要があります。これが正直でない場合は、事前にお詫び申し上げます。Javaポップアップボタン

JToggleButtonJPopupMenuに基づいたSwingコントロールを作成しようとしています。

ポップアップメニューが表示されている場合はトグルボタンが選択され、ポップアップメニューが表示されていない場合はトグルボタンは選択解除されます。したがって、その動作は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)すべてのルックアンドフィールで動作するようにこの問題を解決するにはどうすればよいですか?私はあなたがすべての標準L & Fが自身の特定の問題を持っている金属

  • と比較してJToggleButtonに3つのマウスクリックを必要としていることがわかりニンバスはあまりにバギー(開発が途中でどこかで終了)され

  • +2

    1 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
    • 、特にSystemLookAndFeel

    • JPopupではJWindowを使用してください。JPopupでは別のバグもあります。 JPopup with JCombobox

    +1

    +1で、http://sscce.org/を投稿するため。次に、 'WindowListener'を使用して' windowDeactivated() 'イベントを処理してウィンドウを隠し、トグルボタンをリセットすることもできます。 – camickr

    +0

    お返事ありがとうございます。 OracleがNimbusをjavax.swingに移したのは不思議そうだ。JDK 7で半分しか開発せずに停止した場合は、JDK 7と一緒にパッケージを作成します。 Popupの代わりにJWindowを使用する場合、私はPopup/JPopupMenuで人々が抱えていた問題について興味があります。いつも私にとってうまくいったようですが、私はあまりにも長い間Swingと一緒に働いていません。 – lifelongcoug

    関連する問題