拖动和控制JTree扩展延迟下降

时间:2011-03-31 22:24:30

标签: java swing

我们的系统目前允许用户拖放落在JTree上。当用户将鼠标悬停在树中的节点上时,我们编写了代码来扩展树节点。然而,Java和现代计算机的速度是它们的节点往往会非常快速地扩展。如果用户非常快速地拖动树中的许多节点,则所有节点都会扩展。

我们需要的是在树节点扩展发生之前的一些延迟,可能是一两秒。如果用户没有停留在节点上以获得分配的延迟,则节点不应该扩展。

实现此行为的最佳方法是什么。

2 个答案:

答案 0 :(得分: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线程上,使用现有的ReScheduler实例,只要新节点悬停在其上,您就会执行以下操作:

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

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

做StanislavL建议的实际上会更直接一些。只要将鼠标悬停在组件上,就可以安排将扩展该组件的任务。当任务启动时,请检查用户是否仍然将鼠标悬停在已安排任务的组件上。

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

答案 1 :(得分:1)

当鼠标位于节点上时,您可以使用所需的延迟启动Timer。调用Timer动作时,只需检查鼠标是否仍在同一节点上。如果是,请展开,如果不是什么都不做。