我們的系統當前允許用戶在JTree上拖放&。當用戶懸停在樹中的一個節點上時,我們已經編寫了代碼來展開樹節點。然而,Java和現代計算機作爲節點的速度趨於快速擴展。如果用戶非常快速地拖動樹中的許多節點,則所有節點都會展開。在拖放上控制JTree擴展延遲
我們需要的是在樹節點擴展發生之前的一些延遲,可能是一兩秒。如果用戶沒有在節點上停留在分配的延遲上,該節點不應該擴展,這使事情變得複雜化。
實現此行爲的最佳方式是什麼?
我們的系統當前允許用戶在JTree上拖放&。當用戶懸停在樹中的一個節點上時,我們已經編寫了代碼來展開樹節點。然而,Java和現代計算機作爲節點的速度趨於快速擴展。如果用戶非常快速地拖動樹中的許多節點,則所有節點都會展開。在拖放上控制JTree擴展延遲
我們需要的是在樹節點擴展發生之前的一些延遲,可能是一兩秒。如果用戶沒有在節點上停留在分配的延遲上,該節點不應該擴展,這使事情變得複雜化。
實現此行爲的最佳方式是什麼?
您可以使用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);
}
當鼠標位於節點上時,您可以啓動具有所需延遲的Timer。當調用Timer操作時,只需檢查鼠標是否仍在同一節點上。如果是的話,擴大它,如果不是什麼都不做。
你的答案中的一些更多細節將會有所幫助。 mlaw的答案是使用調度程序和另一個線程來獲取您提到的計時器行爲。你會做什麼不同? – BenjaminLinus 2011-04-01 15:16:39
@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
我會說它會在2秒後打開相同的節點。 – StanislavL 2011-04-01 05:37:56
@StanislavL任務被取消... – 2011-04-01 13:16:22
它可以在您將鼠標移出組件後打開一個節點。 – 2011-04-01 15:44:38