2013-09-24 3 views
5

При попытке щелкнуть по элементу в подменю, естественно быстро нарисовать указатель мыши над пунктами меню под ним. Как Windows, так и Mac изначально обрабатывают это, помещая небольшую задержку перед открытием меню. Swing JMenus не справляется с этим, и меню, которое на короткое время наводит курсор мыши, будет открыто до того, как мышь достигнет намеченного пункта меню.Java Swing - добавление снисхождения при выборе элементов в подменю

Например, на изображении ниже, если бы я попытался выбрать Item 3, но в процессе моей мыши кратко скользил по Menu 2, то Menu 1 подменю исчезнет, ​​прежде чем я добрался до него.

У кого-нибудь есть какие-либо советы или предложения по обойти это? Моя идея состояла в том, чтобы определить пользовательский MenuUI, который добавил таймер к обработчику мыши.

a screen

Вот несколько простых примеров кода, который иллюстрирует мою проблему:

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

[Это сообщение] (http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown) связана с алгоритмом, который решает эту проблему путем изучения путь, по которому движется пользовательская мышь, когда он уходит от элемента к треугольнику, но я не уверен, насколько переносимый сценарий jQuery, связанный в нижней части этого сообщения, будет в рамках Swing. – akbiggs

ответ

0

Я придумал очень хакерское решение.

Я создал класс пользовательского интерфейса, который расширяет BasicMenuUI. Я переопределяю метод createMouseInputListener, чтобы вернуть пользовательский номер MouseInputListener вместо частного handler объекта внутри BasicMenuUI.

Я получил код для MouseInputListener в handler от GrepCode [1] и скопировал его в свой пользовательский прослушиватель. Я сделал одно изменение, поставив таймер в mouseEntered. Мой окончательный код mouseEntered выглядит следующим образом:

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

Перед вызова исходного кода, который был в mouseEntered, я проверяю, чтобы убедиться, что мышь все еще находится в пределах зоны этого параметра меню. Я не хочу, чтобы все меню, которые моя мышь щелкала, появлялась через 100 мс.

Пожалуйста, дайте мне знать, если кто-нибудь нашел лучшее решение для этого.

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

2

вызов setDelay(delay) на вашей menu переменной, где параметр delay является количество миллисекунд, чтобы ждать меню, чтобы показать , как int.

Это следующая строка кода будет установить задержку на 1 секунду, поэтому пользователь должен Наведите курсор мыши на пункт меню «Меню п» 1 секунды, до появления подменю: menu.setDelay(1000);

Вот отрывок из отредактированный код:

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

Это не сработало бы, потому что хотя для подменю для случайного зависания над пунктом меню задержка составляла 1 секунду, желаемое подменю все равно сразу исчезнет, ​​как только ваша мышь надвинется над другим меню. – flutillie

+0

Вот скринкаст того, что я опишу выше, с setDelay (1000): http://tinypic.com/r/2wel1dy/5 – flutillie