JPopupPanel закрывается при нажатии на его JPopupMenu - PullRequest
2 голосов
/ 27 апреля 2011

У меня появляется JPopupPanel при нажатии кнопки.

Этот JPopupPanel имеет JPopupMenu, который появляется при щелчке правой кнопкой мыши и отображает различные варианты. Когда левая кнопка нажата, чтобы выбрать один из этих параметров в PopupMenu, PopupPanel на мгновение закрывается, оставляя PopupMenu самостоятельно, и когда кнопка отпускается, PopupMenu также исчезает (как и ожидалось), но действие не отображается PopupPanel, поскольку она уже закрыта.

Как можно избежать закрытия JPopupPanel при выборе одного из параметров JPopupMenu?

Спасибо

Ответы [ 2 ]

1 голос
/ 20 мая 2011

Я сам сталкивался с этой проблемой при установке пользовательского JPopupMenu на JCommandButton.Для вашего JCommandButton я обнаружил, что это полезно для предотвращения преждевременного удаления родительского всплывающего окна:

this.putClientProperty(BasicCommandButtonUI.DONT_DISPOSE_POPUPS, true);

Если вместо этого вы выбираете JPopupMenu JMenuItem, родительская всплывающая панель остается открытойУ вас есть пара вариантов.Проблема связана с неработающей связью JPopupMenu в цепочке контейнеров предков, на которую опирается пользовательский интерфейс.Вместо 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, так как у меня естьпроблемы с изменением сторонних библиотек.

1 голос
/ 01 мая 2011

Извините, у меня нет опыта использования 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);
            }
        });
    }   
}
...