开发者

JPopupMenu bug/glitch(?) when showing submenu

开发者 https://www.devze.com 2023-01-19 21:28 出处:网络
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 su

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 ma开发者_JS百科in menu is painted over the submenu). I can still navigate it using keyboard.

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

JPopupMenu bug/glitch(?) when showing submenu

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

JPopupMenu bug/glitch(?) when showing submenu

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


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.


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

精彩评论

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