2011-04-27 24 views
2

我點擊一個按鈕時顯示一個JPopupPanelJPopupPanel關閉時點擊其JPopupMenu

這個JPopupPanel有一個JPopupMenu它出現與鼠標右鍵單擊,顯示不同的選項。 當按下左按鈕在PopupMenu中選擇其中一個選項時,PopupPanel關閉使PopupMenu自身暫時停留一段時間,並且釋放按鈕時,PopupMenu也消失(如預期的那樣),但無法看到該操作PopupPanel,因爲它已經關閉了。

如何避免JPopupPanel在選擇JPopupMenu的某個選項時關閉?

謝謝

回答

1

對不起,我沒有使用JPopupPanel的經驗。因此,我只能提供簡單的破解

我會懷疑你可以做一些類似於我的例子(下面),我忽略了隱藏選項選擇上的彈出式菜單。

我的方法是重新顯示選項選項上的彈出式菜單。所以休耕這也許你可以嘗試和隱藏時重新顯示你的面板。

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import javax.swing.JFrame; 
import javax.swing.JMenuItem; 
import javax.swing.JPanel; 
import javax.swing.JPopupMenu; 
import javax.swing.SwingUtilities; 

public class JPopupMenuIgnoreOptionCloseOnClick extends JPanel 
{ 
    private static final long serialVersionUID = 1L; 
    private JPopupMenu popup = new JPopupMenu("Oi I am popup"); 
    private MouseListener mL = new MouseAdapter() 
    { 
     @Override 
     public void mousePressed(MouseEvent e) 
     { 
      System.out.println("mL mousePressed e.isP="+e.isPopupTrigger()); 
      super.mousePressed(e); 
      showPopup(e); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) 
     {   
      System.out.println("mL mouseReleased e.isP="+e.isPopupTrigger()); 
      super.mouseReleased(e); 
      showPopup(e); 
     } 

     private void showPopup(MouseEvent e) 
     { 
      if(e.isPopupTrigger()) 
      { 
       prevLocation = e.getPoint(); 
       popup.show(e.getComponent(), e.getX(), e.getY()); 
      } 
     } 
    }; 
    private Point prevLocation = null; 
    private MouseListener optionML = new MouseAdapter() 
    { 
     @Override 
     public void mouseReleased(MouseEvent e) 
     { 
      System.out.println("optionML mouseReleased prevLocation="+prevLocation); 
      e.consume(); 
      popup.show(JPopupMenuIgnoreOptionCloseOnClick.this, prevLocation.x,prevLocation.y); 
     } 

    }; 

    public JPopupMenuIgnoreOptionCloseOnClick() 
    { 
     addMouseListener(mL); 
     JMenuItem opt1 =new JMenuItem("Option 1"); 
     opt1.addMouseListener(optionML); 
     popup.add(opt1); 
     JMenuItem opt2 =new JMenuItem("Option 2"); 
     opt2.addMouseListener(optionML); 
     popup.add(opt2); 
     JMenuItem opt3 =new JMenuItem("Option 3"); 
     opt3.addMouseListener(optionML); 
     popup.add(opt3); 
    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      {   
       JPopupMenuIgnoreOptionCloseOnClick p = new JPopupMenuIgnoreOptionCloseOnClick(); 
       p.setPreferredSize(new Dimension(400, 400)); 
       JPanel contentPane = new JPanel(); 
       contentPane.setBackground(Color.CYAN); 
       contentPane.add(p); 
       JFrame f = new JFrame();   
       f.setContentPane(contentPane); 
       f.setSize(800, 600); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

@ Boro +1但嗯(對於期貨讀者)如何告訴你可敬的,更好的...你完全忽略了主要方法中的EDT,以及關於LayeredPane的例子* * * * * PrefferedSize容器的孩子,編輯,並把那裏的圖標+按鈕首選大小+10爲優秀的輸出到GUI,如果你編輯,那麼這個評論可以刪除:-) – mKorbel 2011-04-30 23:16:06

+0

@mKorbel感謝您的評論。我對編程一個簡單的解決方案/例子時懶惰解釋了我對EDT的無知(當構建GUI時)。代碼已被編輯。我將從現在開始嘗試在每個示例中添加SwingUtilities.invokeLater()。順便說一句,當GUI構建忽略EDT會導致一個簡單例子的問題時,我從來沒有看到過問題。爲了解釋爲什麼我使用setPreferredSize()作爲滾動窗格,請參閱我的答案下的注2。 PS:不需要刪除你的評論---它將被用作提醒。 – Boro 2011-04-30 23:37:26

+0

「順便說一句,當GUI構建忽略EDT的時候,我從來沒有遇到過任何問題」1 /是直到/然後你會嘗試使用一些原始的L&F,也不是Custom,2/one(一次)(你希望你)userPower不是0.6 T但6T,然後任何新手可以採取這一個作爲編碼標準,3/<:-)>一些人在這裏不會採取setSize()就像懶惰 mKorbel 2011-05-01 00:03:34

1

我在JCommandButton上安裝自定義JPopupMenu時遇到了這個問題。 爲了您JCommandButton我發現這是有幫助防止過早處置父彈出的:

this.putClientProperty(BasicCommandButtonUI.DONT_DISPOSE_POPUPS, true); 

如果你正在尋找的是而不是在製作的JPopupMenu JMenuItem的選擇,家長彈出面板將繼續開放,你有幾個選項。問題源於JPopupMenu在祖先容器鏈中的斷開鏈接,UI依賴於該鏈接。而不是getParent(),你需要返回getInvoker()。

1:
修改BasicPopupPanelUI.WindowTracker.eventDispatched()中的庫源代碼。請更改SwingUtilities .getAncestorOfClass()調用以使用SwingXUtilities .getAncestorOfClass(),它解釋了這種特殊情況。或者自己實施邏輯。

if(parent instanceof JPopupMenu) parent = ((JPopupMenu)parent).getInvoker() 

2:

這個代碼添加到窗口小部件(的CustomButton?)

final JPopupMenu popper = new JPopupMenu(){ //hack 
     @Override public Container getParent(){ 
      StackTraceElement ste = Thread.currentThread().getStackTrace()[2]; 
      if(ste.getClassName().equals(SwingUtilities.class.getName())) 
       return CustomButton.this.getParent(); 
      return super.getParent(); 
     } 
    }; 

我選擇了#2,因爲我有修改的第三方庫的問題。

+0

最後,我做了一些類似於你的建議的事情:重寫SubstancePopupPanelUI類,這樣在內部類WindowTracker2中,可以通過檢查Swingx中的SwingUtilities.getAncestorOfClass()來實現eventDispatched方法中的黑客行爲 不管怎麼說,還是要謝謝你 – spuas 2011-07-07 09:46:37