2013-09-24 9 views
5

Quando si tenta di fare clic su un elemento in un sottomenu, è naturale trascinare rapidamente il mouse sulle voci di menu sottostanti. Sia Windows che Mac gestiscono in modo nativo mettendo un piccolo ritardo prima che un menu venga aperto. Swing JMenus non gestisce questo, e il menu con il mouse si posiziona per qualche istante prima che il mouse raggiunga la voce di menu desiderata.Java Swing - Aggiungi clemenza quando si selezionano elementi nei sottomenu

Per esempio, nell'immagine qui sotto, se ho cercato di selezionare Item 3, ma nel processo mia brevemente topo scivolò Menu 2, il sottomenu Menu 1 scomparirebbe prima ho ottenuto ad esso.

Qualcuno ha qualche consiglio o suggerimento per aggirare questo? La mia idea era quella di definire un MenuUI personalizzato che aggiungesse un timer al gestore del mouse.

a screen

Ecco qualche semplice codice di esempio che illustra il mio problema:

public class Thing extends JFrame { 
    public Thing() 
    { 
     super(); 
     this.setSize(new Dimension(500, 500)); 
     final JPopupMenu pMenu = new JPopupMenu(); 
     for (int i = 0; i < 5; i++) 
     { 
      JMenu menu = new JMenu("Menu " + i); 
      pMenu.add(menu); 
      for (int j = 0; j < 10; j++) 
      { 
       menu.add(new JMenuItem("Item " + j)); 
      } 
     } 

     this.addMouseListener(new MouseAdapter() { 

      @Override 
      public void mouseReleased(MouseEvent e) { 
       pMenu.show(Thing.this, e.getX(), e.getY()); 
      } 
     }); 
    } 

    public static void main(String[] args) 
    { 
     Thing t = new Thing(); 
     t.setVisible(true); 
    } 
} 
+0

[Questo post] (http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown) è relativo a un algoritmo che risolve questo problema esaminando la percorso che il mouse dell'utente prende mentre si allontana dall'oggetto contro un triangolo, ma non sono sicuro di quanto lo script jQuery collegato in fondo a quel post sia portatile al framework Swing. – akbiggs

risposta

0

Mi è venuta una soluzione molto hacky.

Ho creato una classe UI che estende BasicMenuUI. Eseguo l'override del metodo createMouseInputListener per restituire un oggetto personalizzato MouseInputListener anziché l'oggetto privato handler all'interno di BasicMenuUI.

Ho quindi ottenuto il codice per l'implementazione MouseInputListener in handler da GrepCode [1] e l'ho copiato nel mio listener personalizzato. Ho apportato una modifica, mettendo un timer in mouseEntered. Il mio codice finale per mouseEntered assomiglia a questo:

public void mouseEntered(MouseEvent e) { 
     timer.schedule(new TimerTask() { 

      @Override 
      public void run() { 
       if (menuItem.isShowing()) 
       { 
        Point mouseLoc = MouseInfo.getPointerInfo().getLocation(); 
        Point menuLoc = menuItem.getLocationOnScreen(); 
        if (mouseLoc.x >= menuLoc.x && mouseLoc.x <= menuLoc.x + menuItem.getWidth() && 
          mouseLoc.y >= menuLoc.y && mouseLoc.y <= menuLoc.y + menuItem.getHeight()) 
        { 
         originalMouseEnteredStuff(); 
        } 
       } 
      } 
     }, 100); 
    } 

Prima di chiamare il codice originale che era in mouseEntered, controllo per assicurarsi che il mouse è ancora all'interno dell'area di questo menu. Non voglio che tutti i menu che il mio mouse sfiorano vengano visualizzati dopo 100 ms.

Per favore fatemi sapere se qualcuno ha scoperto una soluzione migliore per questo.

[1] http://www.grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/7-b147/javax/swing/plaf/basic/BasicMenuUI.java/?v=source

2

chiamata setDelay(delay) sul menu variabile, in cui il parametro delay è la quantità di millisecondi di attesa per il menu per mostrare , come int.

Questa seguente riga di codice imposterà il ritardo a 1 secondo, quindi l'utente deve mouseover la voce di menu "Menu n" 1 secondo, prima che venga visualizzato il sottomenu: menu.setDelay(1000);

Ecco un frammento della cura codice:

for (int i = 0; i < 5; i++) 
{ 
    JMenu menu = new JMenu("Menu " + i); 
    pMenu.add(menu); 
    for (int j = 0; j < 10; j++) 
    { 
     menu.add(new JMenuItem("Item " + j)); 
    } 
    menu.setDelay(1000); 
} 
+0

Questo non funzionerebbe perché, sebbene il ritardo sarebbe di 1 secondo per il sottomenu per la voce del menu al passaggio del mouse accidentalmente, il sottomenu desiderato scomparirà immediatamente non appena il mouse passa sopra un altro menu. – flutillie

+0

Ecco uno screencast di ciò che descrivo sopra, con setDelay (1000): http://tinypic.com/r/2wel1dy/5 – flutillie

Problemi correlati