java当JTabbedPane不再可见时,如何确保JTabbedPane的内容接收到ComponentEvent(componentHidden)
我有一个应用程序,它使用JTabbedPane来显示几个不同的选项卡。其中一个选项卡运行线程以显示其内容。我已经实现了一个ComponentListener,在选项卡不可见时停止线程。我可以看到,当选项卡被选中时,线程将变为活动状态,当不可见时,线程将停止,这与预期的完全一样
如果在未选择带有线程的选项卡时关闭应用程序,则一切正常,应用程序关闭。如果在带有线程的选项卡可见时关闭应用程序,则该选项卡不会收到ComponentEvent,因此线程保持活动状态,我需要手动终止应用程序(使用Eclipse控制台上的Terminate按钮)
我宁愿不使用这个系统。方法关闭我的应用程序,但停止所有线程并释放所有窗口。这就像一个符咒,除了这一个标签与它的线程
在处理窗口或removeAll()之前,我已尝试将JTabbedPane设置为不可见。两者都没有达到预期的结果。removeAll()甚至产生了相反的结果。如果该选项卡未处于活动状态,它将接收一个ComponentEvent,以指示该事件已变为可见(ComponentShowed)(实际上,所有选项卡都将依次接收该事件,但没有一个选项卡将获得componentHidden)
显然,当我通过文件菜单关闭窗口时(我有一些控制权,在这里我测试了removeAll和setVisible(false)方法),以及当窗口被释放时,线程都应该停止,因为用户单击窗口角落的十字
更新
我已经找到了一种方法,可以使导致问题的线程按照建议作为守护进程线程运行。然而,这导致了一个意想不到的问题。启动问题线程的类是我正在使用的JUNG软件包中的VisRunner类。它包含一个启动线程的方法“relax”
@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();
}
}
我加载relaxer,如下所示:
visModel = new DefaultVisualizationModel<>(layout);
visModel.setRelaxer(new MyVisRunner(layout));
我本以为这能解决问题,但这只会增加问题。当我现在启动软件时,它不会停止,即使有问题的选项卡甚至不可见(该选项卡已构建,但不可见)。在这种情况下,甚至没有调用MyVisRunner的relax方法;该线程未在VisRunner类中的任何其他位置初始化。注释掉setRelaxer行将解决这个额外的问题(显然保留原来的问题)
更新2
我终于解决了这个问题。我没有意识到,当我设置自己的relaxer时,已经有一个relaxer在运行。我已将代码调整为:
visModel = new DefaultVisualizationModel<>(layout);
visModel.getRelaxer().stop();
visModel.setRelaxer(new MyVisRunner(layout));
这既解决了额外的问题,也解决了我原来的问题
# 1 楼答案
您应该将该线程设置为守护进程线程:
如果不再有运行的非守护进程线程,虚拟机将终止
顺便说一句,您可以在
JFrame
上为windowClosing
事件添加WindowListener