2010-10-10 4 views
3

J'ai cet étrange bug avec mon menu contextuel. Cela arrive rarement et semble aléatoire. Le problème est quand j'ai un sous-menu dans mon JPopupMenu - quand je sélectionne le sous-menu, le menu principal disparaît et le sous-menu est peint incorrectement (c'est comme si le tampon du menu principal est peint sur le sous-menu). Je peux toujours naviguer à l'aide du clavier.JPopupMenu bug/glitch (?) Lors de l'affichage du sous-menu

Voici quelques captures d'écran: Voici comment il devrait ressembler

alt text

Et voici à quoi il ressemble quand le bug apparaît:

alt text

Alors que pépin sur la deuxième image est l'endroit où le sous-menu aurait dû être.

Ce qui pourrait causer cela? Il n'y a pas d'exceptions levées, cela ne semble pas lié à la plateforme, donc je n'ai aucune idée de comment réduire cela. S'il vous plaît aider.

EDIT Ci-dessous un sscce qui reproduit le problème:

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

Répondre

2

Grâce à un de mes utilisateurs, j'ai trouvé un problème. Juste au cas où quelqu'un piraterait plus qu'il ne le devrait - c'est ce qui s'est passé: dans une partie de mon programme, je montre un message sur un JProgressBar montrant la position lorsque l'utilisateur bouge le pouce de la barre de progression . Pour ce faire, je crée un Popup en utilisant un PopupFactory. Puis, en utilisant des écouteurs de souris, je montre et cache le popup. Après que j'appelle hide() je n'ai pas placé l'objet de popup à null qui peut avoir conduit à appeler le hide() deux fois, ou en gardant le popup de gc - ne sais pas exactement. Mais apparemment, cela a chamboulé le mécanisme de popup de JPopupMenu.

Citation de Popup.hide() JavaDoc explique mieux:

Hides et dispose du Popup. Une fois qu'un Popup a été éliminé, vous ne devez plus invoquer de méthodes dessus. Un Popup éliminé peut être récupéré et utilisé ultérieurement en fonction de PopupFactory. En tant que tel, si vous invoquez des méthodes sur un Popup éliminé, un comportement indéterminé en résultera.

+0

Ensuite, la solution est de définir l'objet à null? – elias

+0

@Elias: la solution était d'empêcher d'appeler des méthodes sur un popup après l'avoir caché et éliminé. –

0

Je ne sais pas si cela va aider votre problème, mais normalement le menu contextuel doit être ajouté de cette façon:

table.setComponentPopupMenu(popup); 
+1

Merci, mais je dois sélectionner des lignes après un clic droit et votre méthode ne le permet pas. J'ai trouvé une solution, je l'afficherai plus tard. –

Questions connexes