0

我有一个使用 JTabbedPane 来显示几个不同选项卡的应用程序。这些选项卡之一有一个线程正在运行以显示其内容。我已经实现了一个 ComponentListener 以在选项卡不可见时停止线程。I can see the thread becoming active when the tab is selected and stopping when becoming invisible, quite as expected.

如果我在未选择带有线程的选项卡时关闭我的应用程序,那么一切顺利并且应用程序关闭。如果在带有线程的选项卡可见时关闭应用程序,则选项卡不会收到 ComponentEvent,因此线程保持活动状态,我需要手动终止应用程序(使用 Eclipse 控制台上的终止按钮)。

我不喜欢使用 System.exit() 方法来关闭我的应用程序,而是停止所有线程并释放所有窗口。这就像一个魅力,除了这个带有它的线程的标签。

在处理我的窗口或 removeAll() 之前,我已经尝试将 JTabbedPane 设置为不可见。也没有预期的结果。removeAll() 甚至有相反的结果。如果选项卡未处于活动状态,它将收到一个 ComponentEvent 来指示它已变为可见 (componentShown)(实际上,所有选项卡都会依次接收该事件,但没有一个会收到 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();
   }
}

我这样加载松弛器:

  visModel = new DefaultVisualizationModel<>(layout);
  visModel.setRelaxer(new MyVisRunner(layout));

我原以为这可以解决问题,但它只会增加问题。当我现在启动我的软件时,它不会停止,即使有问题的选项卡甚至不可见(选项卡已构建,但不可见)。在这种情况下,甚至没有调用 MyVisRunner 的松弛方法;该线程未在 VisRunner 类的其他任何地方初始化。注释掉 setRelaxer 行将解决这个额外的问题(显然保留原来的问题)。

更新 2

我终于解决了这个问题。我没有意识到,当我设置自己的松弛器时,已经有一个松弛器在运行。我已将代码调整为:

  visModel = new DefaultVisualizationModel<>(layout);
  visModel.getRelaxer().stop();
  visModel.setRelaxer(new MyVisRunner(layout));

这解决了额外的问题以及我原来的问题。

4

1 回答 1

1

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

myThread.setDaemon(true);

如果没有更多运行的非守护线程,虚拟机将终止。


顺便说一句,您可以WindowListener在您JFramewindowClosing事件中添加一个。

于 2013-02-26T08:26:52.457 回答