![](/img/trans.png)
[英]How can I refresh a JPanel in a JTabbedPane only if that tab is the one that is visible?
[英]How can I ensure that the contents of a JTabbedPane received a ComponentEvent (componentHidden) when the JTabbedPane is no longer visible
我有一個使用JTabbedPane來顯示幾個不同選項卡的應用程序。 這些選項卡之一的線程正在運行以顯示其內容。 我已經實現了ComponentListener,以在選項卡不可見時停止線程。 我可以看到,當選擇了選項卡時,線程將變為活動狀態,而在不可見時將停止,這完全符合預期。
如果在未選擇帶有線程的選項卡的情況下關閉我的應用程序,則一切順利,並且該應用程序關閉。 如果在顯示帶有線程的選項卡時關閉我的應用程序,則該選項卡沒有收到ComponentEvent,因此線程保持活動狀態,我需要手動終止應用程序(使用Eclipse中控制台上的Terminate按鈕)。
我不想使用System.exit()方法關閉應用程序,而是停止所有線程並處理所有窗口。 這就像一個咒語一樣工作,除了這個帶有線程的選項卡。
我已經嘗試在放置窗口或removeAll()之前將JTabbedPane設置為不可見。 兩者都沒有取得預期的結果。 removeAll()甚至具有相反的結果。 如果選項卡未處於活動狀態,則它將接收一個ComponentEvent,以指示該選項卡已變為可見狀態(componentShown)(實際上,所有選項卡將依次接收該事件,但沒有一個組件會被componentHidden接收)。
顯然,當我通過文件菜單關閉窗口時(在該菜單上我有一些控制權,在這里我已經測試了removeAll和setVisible(false)方法),以及在由於用戶單擊而丟棄窗口時,都應停止線程在窗角的十字架上。
更新資料
我已經找到一種方法來使似乎導致該問題的線程按照建議的那樣作為守護程序線程運行。 然而,這導致了意外的問題。 啟動有問題的線程的類是我使用的JUNG軟件包中的VisRunner類。 它包含一個啟動線程的“放松”方法。
@Override
public void relax() {
// in case its running
stop();
stop = false;
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
我創建了MyVisRunner類:
import edu.uci.ics.jung.algorithms.layout.util.VisRunner;
import edu.uci.ics.jung.algorithms.util.IterativeContext;
public class MyVisRunner extends VisRunner {
public MyVisRunner(final IterativeContext process) {
super(process);
}
@Override
public void relax() {
// in case it's running
Log.d("Relaxing");
stop();
stop = false;
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.setDaemon(true);
thread.start();
}
}
我這樣加載放松器:
visModel = new DefaultVisualizationModel<>(layout);
visModel.setRelaxer(new MyVisRunner(layout));
我原本希望這可以解決問題,但只會增加問題。 現在,當我啟動軟件時,即使有問題的選項卡甚至不可見(該選項卡已構建,但也不可見),它也不會停止。 在這種情況下,甚至沒有調用MyVisRunner的Relax方法。 該線程未在VisRunner類中的其他任何地方初始化。 注釋掉setRelaxer行將解決此附加問題(顯然保留了原始問題)。
更新2
我終於解決了問題。 我沒有意識到當我設置自己的放松器時,已經有一個放松器在運行。 我已將代碼調整為:
visModel = new DefaultVisualizationModel<>(layout);
visModel.getRelaxer().stop();
visModel.setRelaxer(new MyVisRunner(layout));
這解決了其他問題以及我原來的問題。
您應該將線程設置為守護程序線程:
myThread.setDaemon(true);
如果沒有更多正在運行的非守護線程,則虛擬機將終止。
順便說一句,您可以在JFrame
上添加一個WindowListener
來處理windowClosing
事件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.