显示子菜单时的 JPopupMenu bug/glitch(?)

发布于 2024-09-26 23:43:09 字数 2699 浏览 2 评论 0原文

我的弹出菜单有这个奇怪的错误。这种情况很少发生,而且看起来是随机的。问题是当我的 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);
    }
}

I have this strange bug with my popup menu. It happens rarely and seemingly randomly. The problem is when I have a submenu in my JPopupMenu - when I select the submenu, main menu disappears and the submenu is painted incorrectly (it's like the buffer of main menu is painted over the submenu). I can still navigate it using keyboard.

Here are some screenshots:
This is how it should look like

alt text

And this is what it looks like when the bug appears:

alt text

So that glitch on the second picture is where the submenu should've been.

What could cause this? There are no exceptions thrown, it doesn't seem platform-related, so I have no idea how to narrow this down. Please help.

EDIT Below is a sscce that reproduces the problem:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

煮酒 2024-10-03 23:43:09

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

以防万一有人使用 swing 的次数超过了他们应该做的 - 这就是发生的事情:在我的程序的一部分中,我在 JProgressBar 上显示一条弹出消息,显示当用户移动进度条的拇指时的位置。为此,我使用 PopupFactory 创建一个 Popup。然后,使用鼠标侦听器显示和隐藏弹出窗口。在调用 hide() 后,我没有将弹出对象设置为 null,这可能会导致调用 hide() 两次,或者保持gc 的弹出窗口 - 不太清楚。但显然这搞乱了 JPopupMenu 的弹出机制。

引用 Popup.hide() JavaDoc 对此进行了更好的解释:

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

Thanks to one of my users, I've found a problem.

Just in case someone is hacking with swing more than they should do - this is what happened: in one part of my program I show a popup message on a JProgressBar showing position when the user is moving the thumb of the progress bar. To do this, I create a Popup using a PopupFactory. Then, using mouse listeners, I show and hide the popup. After I call hide() I didn't set the popup object to null which may led to calling the hide() twice, or keeping the popup from gc - don't know exactly. But apparently this messed up JPopupMenu's popup mechanism.

Quote from Popup.hide() JavaDoc explains it better:

Hides and disposes of the Popup. Once a Popup has been disposed you should no longer invoke methods on it. A disposed Popup may be reclaimed and later used based on the PopupFactory. As such, if you invoke methods on a disposed Popup, indeterminate behavior will result.

世界和平 2024-10-03 23:43:09

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

table.setComponentPopupMenu(popup);

I'm not sure if it's going to help with your issue but normally the popup menu should be added that way:

table.setComponentPopupMenu(popup);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文