开发者

JPopupPanel closed when click on its JPopupMenu

开发者 https://www.devze.com 2023-03-01 12:54 出处:网络
I have a JPopupPanel showing up when a button is clicked. This JPopupPanel has a JPopupMenu which shows up with the mouse right click, showing different options.

I have a JPopupPanel showing up when a button is clicked.

This JPopupPanel has a JPopupMenu which shows up with the mouse right click, showing different options. When left button pressed to choose one of this options in the PopupMenu, the PopupPanel closes leaving the PopupMenu by itself for a moment, and when the button is released, the PopupMenu also dissapears (as expected), 开发者_JAVA技巧but the action cannot be seen in the PopupPanel since it is already closed.

How can I avoid the JPopupPanel to close when choosing one of the options of the JPopupMenu?

Thanks


Sorry I do not have experience using JPopupPanel. Thus, I can only offer a simple hack.

I would suspect that you can do something similar as in my example (below) where I 'ignore' hiding popup menu on an option select.

My approach here is to reshow the popup menu on an option selection. So fallowing this maybe you can try and reshow your panel when it hides.

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);
            }
        });
    }   
}


I came across this problem myself when installing a custom JPopupMenu on a JCommandButton. For your JCommandButton I found this to be helpful in preventing premature disposal of the parent popup:

this.putClientProperty(BasicCommandButtonUI.DONT_DISPOSE_POPUPS, true);

If what you are looking for is instead that upon making a JPopupMenu JMenuItem selection, the parent popup panel will stay open, you have a couple options. The problem stems from JPopupMenu's broken link in the ancestry container chain, on which the UI relies. Instead of getParent(), you need to return getInvoker().

1:
modify the library source in BasicPopupPanelUI.WindowTracker.eventDispatched(). Either change the SwingUtilities.getAncestorOfClass() calls to use SwingXUtilities.getAncestorOfClass() which accounts for this special case. Or implement the logic yourself.

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

2:

Add this code to the widget (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();
        }
    };

I chose #2, since I have issues with modifying 3rd party libraries.

0

精彩评论

暂无评论...
验证码 换一张
取 消