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

时间:2010-10-10 06:41:27

标签: java swing submenu jpopupmenu

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

以下是一些截图: 这就是它应该是什么样子

alt text

这就是出现错误时的样子:

alt text

因此,第二张图片上的故障是子菜单应该出现的位置。

是什么导致这个?没有抛出异常,它似乎与平台无关,所以我不知道如何缩小它。请帮忙。

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

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

2 个答案:

答案 0 :(得分:2)

感谢我的一位用户,我发现了一个问题。

万一有人用摇摆比他们应该做的更多 - 这就是发生的事情:在我的程序的一部分中,我在JProgressBar上显示一个弹出消息,显示当用户移动进度条的拇指时的位置。为此,我使用Popup创建PopupFactory。然后,使用鼠标监听器,我显示并隐藏弹出窗口。在我调用hide()之后,我没有将弹出对象设置为null,这可能导致调用hide()两次,或者保持弹出窗口与gc - 不完全确切。但显然这搞砸了JPopupMenu的弹出机制。

来自Popup.hide()的引用JavaDoc更好地解释了它:

  

隐藏和处置Popup。一旦弹出Popup,你就不应该再调用它了。可以回收处理的弹出窗口,然后根据PopupFactory使用。因此,如果在已释放的弹出窗口上调用方法,将导致不确定的行为。

答案 1 :(得分:0)

我不确定它是否会对您的问题有所帮助,但通常应该以这样的方式添加弹出菜单:

table.setComponentPopupMenu(popup);