2013-09-24 43 views
5

尝试点击子菜单中的项目时,很自然地可以在您的鼠标下面的菜单项中快速绘制鼠标。 Windows和Mac本身通过在菜单打开之前放置一个小延迟来处理这个问题。 Swing JMenus不处理这个问题,并且在鼠标到达想要的菜单项之前,鼠标暂时盘旋的菜单将被打开。例如,在下图中,如果我尝试选择Item 3,但在此过程中,我的鼠标短暂滑过Menu 2,则Menu 1子菜单会在我到达之前消失。Java Swing - 在子菜单中选择项目时添加宽大

有没有人有任何提示或建议来解决这个问题?我的想法是定义一个自定义的MenuUI,为其鼠标处理程序添加一个计时器。

a screen

下面是一些简单的示例代码,说明我的问题:你的menu变量,其中delay参数是毫秒等待菜单显示量

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

我想出了一个非常hacky的解决方案。

我做了一个扩展BasicMenuUI的UI类。我重写createMouseInputListener方法返回MouseInputListener而不是BasicMenuUI中的私人handler对象。

然后,我从GrepCode [1]获得handlerMouseInputListener实现的代码,并将其复制到我的自定义侦听器中。我做了一个更改,在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 ms后弹出。

如果有人发现了更好的解决方案,请让我知道。

[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) ,作为一个int。

这下面的代码将延迟设置为1秒,因此,用户必须将鼠标放置在菜单项“菜单N” 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