java - 当 JTabbedPane 不再可见时,如何确保 JTabbedPane 的内容收到 ComponentEvent (componentHidden)

标签 java jtabbedpane jung

我有一个使用 JTabbedPane 来显示多个不同选项卡的应用程序。这些选项卡之一有一个正在运行的线程来显示其内容。我已经实现了一个 ComponentListener 来在选项卡不可见时停止线程。我可以看到线程在选择选项卡时变得活跃,并在变得不可见时停止,正如预期的那样。

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

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

在处置我的窗口或removeAll()之前,我已经尝试将 JTabbedPane 设置为不可见。两者都没有达到预期的结果。 removeAll() 甚至有相反的结果。如果选项卡未处于 Activity 状态,它将收到一个 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 中的relax 方法甚至还没有被调用;该线程未在 VisRunner 类中的其他任何地方初始化。注释掉 setRelaxer 行将解决这个额外的问题(显然保留了原始问题)。

更新2

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

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

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

最佳答案

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

myThread.setDaemon(true);

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

<小时/>

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

关于java - 当 JTabbedPane 不再可见时,如何确保 JTabbedPane 的内容收到 ComponentEvent (componentHidden),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15084387/

相关文章:

java - 在 hibernate 实体和数据传输对象之间转换的好模式是什么?

graph - JUNG 循环树布局

java - SharedPreferences 没有更新其值

java - 如何创建两个具有相同实体的类?

java.lang.ClassNotFoundException : org. junit.runners.BlockJUnit4ClassRunner

java - 如何在 JTabbedPane 的选项卡之间共享 Java 信息

java - Jtabbedpane 两侧的选项卡

java - 为什么 JTabbedPane 的 ChangeListener 会随着主 JFrame 的启动而加载?

java - 在 JUNG 中更改顶点的大小/颜色

java - 创建一个 DelegateForest 并以预先确定的顺序显示它