[英]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.