2013-09-24 7 views
5

Podczas próby kliknięcia elementu w podmenu, naturalnym jest szybkie przesuwanie myszy po elementach menu znajdujących się pod nim. Zarówno system Windows, jak i Mac radzą sobie z tym bez problemu, wprowadzając niewielkie opóźnienie przed otwarciem menu. Huśtawka JMenus nie radzi sobie z tym, a menu, na które na chwilę zostanie zawieszona mysz, zostanie otwarte, zanim mysz osiągnie zamierzony element menu.Java Swing - dodawaj oblężenie przy wybieraniu pozycji w podmenu

Na przykład na poniższym obrazku, jeśli próbowałem wybrać Item 3, ale w trakcie mojej myszy krótko przesuwane na Menu 2, podmenu Menu 1 zniknie, zanim do niego dotarłem.

Czy ktoś ma jakieś wskazówki lub sugestie dotyczące obejścia tego? Mój pomysł polegał na zdefiniowaniu niestandardowego MenuUI, które dodało zegar do myszy.

a screen

Oto prosty przykład kodu, który ilustruje mój problem:

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

[To stanowisko] (http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown) jest związane z algorytmem, który rozwiązuje ten problem poprzez badanie ścieżka, którą odbiera mysz użytkownika, gdy odsuwa się od elementu względem trójkąta, ale nie jestem pewna, jak przenośny skrypt jQuery połączony na dole tego posta byłby ze strukturą Swing. – akbiggs

Odpowiedz

0

Wpadłem na bardzo niełatwe rozwiązanie.

Zrobiłem klasę interfejsu użytkownika, która rozszerza BasicMenuUI. Zastępuję metodę createMouseInputListener, aby zwrócić niestandardowy obiekt MouseInputListener zamiast prywatnego obiektu handler wewnątrz BasicMenuUI.

Następnie otrzymałem kod dla implementacji MouseInputListener w handler z kodu GrepCode [1] i skopiowałem go do mojego niestandardowego detektora. Wprowadziłem jedną zmianę, ustawiając zegar w mouseEntered. Mój kod końcowy dla mouseEntered wygląda następująco:

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

Przed wywołaniem oryginalny kod, który był w mouseEntered, to sprawdź, czy mysz jest nadal w obszarze tym menu jest. Nie chcę, aby wszystkie menu myszy przesuwały się po 100 ms.

Proszę dać mi znać, jeśli ktoś znalazł lepsze rozwiązanie tego problemu.

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

2

połączenia setDelay(delay) o zmiennej menu, gdzie parametr delay jest ilość milisekund czekać na menu, aby pokazać , jako int.

to następujący wiersz kodu będzie ustawić opóźnienie do 1 sekundy, dzięki czemu użytkownik ma do mouseover „Menu n” z menu 1 sekundę, zanim zostanie wyświetlone podmenu: menu.setDelay(1000);

Oto fragment edytowany kod:

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

To nie zadziała, ponieważ chociaż opóźnienie będzie wynosić 1 sekundę dla podmenu przypadkowo zawieszonego nad elementem menu, żądane submenu będzie natychmiast znikać, gdy tylko mysz znajdzie się nad innym menu. – flutillie

+0

Oto screencast tego, co opisałem powyżej, z setDelay (1000): http://tinypic.com/r/2wel1dy/5 – flutillie