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
And this is what it looks like when the bug appears:
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);
精彩评论