有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    您应该将该线程设置为守护进程线程:

    myThread.setDaemon(true);
    

    如果不再有运行的非守护进程线程,虚拟机将终止


    顺便说一句,您可以在JFrame上为windowClosing事件添加WindowListener