2011-03-31 31 views
3

我们的系统当前允许用户在JTree上拖放&。当用户悬停在树中的一个节点上时,我们已经编写了代码来展开树节点。然而,Java和现代计算机作为节点的速度趋于快速扩展。如果用户非常快速地拖动树中的许多节点,则所有节点都会展开。在拖放上控制JTree扩展延迟

我们需要的是在树节点扩展发生之前的一些延迟,可能是一两秒。如果用户没有在节点上停留在分配的延迟上,该节点不应该扩展,这使事情变得复杂化。

实现此行为的最佳方式是什么?

回答

3

您可以使用ScheduledExecutorService执行任务以在给定延迟后展开节点。您也可以在用户移过新节点时取消挂起的任务。

例:

public class ReScheduler { 
    private ScheduledFuture<?> currentTask = null; 
    private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); 
    public void schedule(Runnable command, long delay, TimeUnit units) { 
    if (currentTask != null) { 
     currentTask.cancel(); 
     currentTask = null; 
    } 
    currentTask = executor.schedule(command, delay, units); 
    } 
} 

在您的客户端代码,Swing的UI线程上,用再调度的现有实例,每当一个新的节点上空盘旋,你会做以下几点:

myRescheduler.schedule(new Runnable() { 
    public void run() { 
     SwingUtilities.invokeLater(task to expand the node in the tree!); 
    } 
}, 2, TimeUnit.SECONDS); 

为了获得最佳实践,您应该为“Executors.newScheduledThreadPool”提供一个线程工厂,它将为创建的线程命名。就像NamedThreadFactory

斯坦尼斯拉夫建议的做法实际上会更直接一点。无论何时将鼠标悬停在某个组件上,都需要安排一个将扩展该组件的任务。当任务启动时,让它检查用户是否仍然悬停在组件上,该组件调度任务。

public void hovered() { 
     final Component node = node currently hovered over; // node is the component 
// that is causing the task to be scheduled 
     executor.schedule(new Runnable() { 
     public void run() { 
      // see if the node that the mouse is over now is the same node it was over 2 seconds ago 
      if (getComponentUnderMouse() == node) { 
      expand(node); // do this on the EDT 
      } else { 
      // do nothing because we are over some other node 
      } 
     } 
     }, 2, TimeUnit.SECONDS); 
    } 
+0

我会说它会在2秒后打开相同的节点。 – StanislavL 2011-04-01 05:37:56

+0

@StanislavL任务被取消... – 2011-04-01 13:16:22

+0

它可以在您将鼠标移出组件后打开一个节点。 – 2011-04-01 15:44:38

1

当鼠标位于节点上时,您可以启动具有所需延迟的Timer。当调用Timer操作时,只需检查鼠标是否仍在同一节点上。如果是的话,扩大它,如果不是什么都不做。

+0

你的答案中的一些更多细节将会有所帮助。 mlaw的答案是使用调度程序和另一个线程来获取您提到的计时器行为。你会做什么不同? – BenjaminLinus 2011-04-01 15:16:39

+0

@BenjaminLinus StanislavL的解决方案更直截了当。您将鼠标悬停在组件上,然后:'最终组件originatingComponent = origComp; executor.schedule(new Runnable(){public void run(){if mouse over the originatingComponent,expand。else,do nothing。}},2,TimeUnit.SECONDS); – 2011-04-01 15:47:06