2011-03-31 54 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