Java JPopupMenu在显示子菜单时出现错误/故障(?)

Java JPopupMenu在显示子菜单时出现错误/故障(?),java,swing,submenu,jpopupmenu,Java,Swing,Submenu,Jpopupmenu,我的弹出菜单有一个奇怪的错误。这种情况很少发生,而且似乎是随机发生的。问题是当我的JPopupMenu中有一个子菜单时——当我选择子菜单时,主菜单消失,子菜单绘制错误(就像主菜单的缓冲区绘制在子菜单上一样)。我仍然可以用键盘导航 以下是一些屏幕截图: 应该是这样的 这就是bug出现时的样子: 所以第二张图片上的小故障就是子菜单应该出现的地方 这是什么原因造成的?没有抛出异常,它似乎与平台无关,所以我不知道如何缩小范围。请帮忙 编辑以下是重现问题的SSCE: import javax.swin

我的弹出菜单有一个奇怪的错误。这种情况很少发生,而且似乎是随机发生的。问题是当我的JPopupMenu中有一个子菜单时——当我选择子菜单时,主菜单消失,子菜单绘制错误(就像主菜单的缓冲区绘制在子菜单上一样)。我仍然可以用键盘导航

以下是一些屏幕截图: 应该是这样的

这就是bug出现时的样子:

所以第二张图片上的小故障就是子菜单应该出现的地方

这是什么原因造成的?没有抛出异常,它似乎与平台无关,所以我不知道如何缩小范围。请帮忙

编辑以下是重现问题的SSCE:

import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Test {
    private static Popup popup;

    public static void main(String[] args) {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                showMenu(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                showMenu(e);
            }

            private void showMenu(final MouseEvent e) {
                if (e.isPopupTrigger()) {
                    JPopupMenu menu = new JPopupMenu();
                    JMenu subMenu = new JMenu("SubMenu");
                    menu.add(subMenu);

                    subMenu.add("Item 1");
                    subMenu.add("Item 2").addMouseMotionListener(new MouseAdapter() {
                        @Override
                        public void mouseMoved(MouseEvent e) {
                            hidePopup();
                            // this is where I call the hide twice, in my case it was
                            // caused by some action or mouse listener calling it twice
                            hidePopup();
                            showPopup(e, frame);
                        }
                    });
                    subMenu.add("Item 3");

                    menu.show(frame.getContentPane(), e.getX(), e.getY());
                }
            }

            private void showPopup(MouseEvent e, JFrame frame) {
                PopupFactory popupFactory = PopupFactory.getSharedInstance();
                JToolTip toolTip = new JToolTip();
                toolTip.setTipText("wfkwdlpfhd ");
                popup = popupFactory.getPopup(frame, toolTip, e.getXOnScreen(), e.getYOnScreen());
                popup.show();
            }

            private void hidePopup() {
                if (popup != null)
                    popup.hide();
            }
        });

        frame.setSize(300, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

我不确定它是否有助于解决您的问题,但通常应以这种方式添加弹出菜单:

table.setComponentPopupMenu(popup);

多亏了我的一个用户,我发现了一个问题

以防万一,有人对swing的攻击超出了他们应该做的——事情就是这样:在我的程序的一部分中,我在JProgressBar上显示了一条弹出消息,显示了当用户移动进度条的拇指时的位置。为此,我使用
PopupFactory
创建了一个
弹出窗口。然后,使用鼠标侦听器显示和隐藏弹出窗口。调用
hide()
后,我没有将弹出对象设置为
null
,这可能导致调用
hide()
两次,或者从gc中保留弹出窗口-我不知道确切情况。但显然,这打乱了JPopMenu的弹出机制

引用
Popup.hide()
JavaDoc更好地解释了这一点:

隐藏和处理弹出窗口。一旦弹出窗口被释放,您就不应该再调用它上的方法。处理后的弹出窗口可以回收,并在以后基于弹出工厂使用。同样地,如果在已处理的弹出窗口上调用方法,将导致不确定的行为


谢谢,但我需要在右键单击后选择行,而您的方法不允许这样做。我找到了一个解决方案,稍后再发布。那么解决方案是将对象设置为null?@Elias:解决方案是防止在隐藏和处理弹出窗口后调用任何方法。