2010-10-10 35 views
3

我有我的弹出菜单这个奇怪的错误。它很少发生,看似随机发生。问题是当我在我的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

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

只是为了防止有人在使用swing时发生超过他们应该做的事 - 这就是发生了什么:在我的程序的一部分中,当用户移动进度条的拇指时,我在JProgressBar上显示弹出消息。为此,我使用PopupFactory创建了一个Popup。然后,使用鼠标监听器,我显示并隐藏弹出窗口。在我致电hide()后,我没有将弹出窗口对象设置为null,这可能导致调用hide()两次,或者保留gc的弹出窗口 - 不确切地知道。但显然这弄糟了JPopupMenu的弹出机制。

报价从Popup.hide()的JavaDoc更好地解释它:

隐藏和弹出的处置。一旦弹出窗口被处置,你不应该再调用它的方法。一个处理过的Popup可能会被回收并在稍后基于PopupFactory使用。因此,如果您调用处置Popup的方法,则会导致不确定的行为。

+0

那么解决方案是将对象设置为null? – elias 2013-07-17 14:00:40

+0

@Elias:解决方案是防止在隐藏和处理弹出窗口后调用任何方法。 – 2013-07-17 16:36:53

0

我不知道这是否会帮助您解决问题,但通常应加入弹出式菜单的方式:

table.setComponentPopupMenu(popup); 
+1

谢谢,但我需要选择行后右键单击和您的方法不允许这样做。我找到了一个解决方案,稍后会发布。 – 2010-10-10 10:34:53