简体   繁体   English

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

[英]How can I ensure that the contents of a JTabbedPane received a ComponentEvent (componentHidden) when the JTabbedPane is no longer visible

I have an application that uses a JTabbedPane to show several different tabs. 我有一个使用JTabbedPane来显示几个不同选项卡的应用程序。 One of these tabs has a thread running to display it's contents. 这些选项卡之一的线程正在运行以显示其内容。 I have already implemented a ComponentListener to stop the thread when the tab is not visible. 我已经实现了ComponentListener,以在选项卡不可见时停止线程。 I can see the thread becoming active when the tab is selected and stopping when becoming invisible, quite as expected. 我可以看到,当选择了选项卡时,线程将变为活动状态,而在不可见时将停止,这完全符合预期。

If I close my application when the tab with the thread is not selected, everything goes well and the application closes. 如果在未选择带有线程的选项卡的情况下关闭我的应用程序,则一切顺利,并且该应用程序关闭。 If I close my application when the tab with the thread is visible, the tab does not receive a ComponentEvent, so the thread stays active and I need to kill the application by hand (using the Terminate button on the console in Eclipse). 如果在显示带有线程的选项卡时关闭我的应用程序,则该选项卡没有收到ComponentEvent,因此线程保持活动状态,我需要手动终止应用程序(使用Eclipse中控制台上的Terminate按钮)。

I prefer not to use the System.exit() method to close my application, but rather stop all threads and dispose all windows. 我不想使用System.exit()方法关闭应用程序,而是停止所有线程并处理所有窗口。 This is working like a charm, except for this one tab with it's thread. 这就像一个咒语一样工作,除了这个带有线程的选项卡。

I have already tried to set the JTabbedPane to invisible before disposing my window, or removeAll(). 我已经尝试在放置窗口或removeAll()之前将JTabbedPane设置为不可见。 Neither had the expected result. 两者都没有取得预期的结果。 The removeAll() even had the opposite result. removeAll()甚至具有相反的结果。 If the tab was not active, it would receive a ComponentEvent to indicate that is had become visible (componentShown) (actually, all tabs would receive the event in turn, but none would get a componentHidden). 如果选项卡未处于活动状态,则它将接收一个ComponentEvent,以指示该选项卡已变为可见状态(componentShown)(实际上,所有选项卡将依次接收该事件,但没有一个组件会被componentHidden接收)。

Obviously, the thread should be stopped both when I close the window via the file menu (over which I have some control and where I have tested the removeAll and setVisible(false) methods) as well as when the window is disposed because the user clicks on the cross in the window corner. 显然,当我通过文件菜单关闭窗口时(在该菜单上我有一些控制权,在这里我已经测试了removeAll和setVisible(false)方法),以及在由于用户单击而丢弃窗口时,都应停止线程在窗角的十字架上。

Update 更新资料

I have found a way to make the thread that seems to cause the problem run as daemon thread as suggested. 我已经找到一种方法来使似乎导致该问题的线程按照建议的那样作为守护程序线程运行。 This has however led to an unexpected problem. 然而,这导致了意外的问题。 The class that started the problematic thread was the VisRunner class from the JUNG software package I am using. 启动有问题的线程的类是我使用的JUNG软件包中的VisRunner类。 It contains a method "relax" in which the thread is started. 它包含一个启动线程的“放松”方法。

  @Override
  public void relax() {
      // in case its running
      stop();
      stop = false;
      thread = new Thread(this);
      thread.setPriority(Thread.MIN_PRIORITY);
      thread.start();
 }

I have created the MyVisRunner class: 我创建了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();
   }
}

I load the relaxer as such: 我这样加载放松器:

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

I would have expected this to solve the problem, but it only increases the problem. 我原本希望这可以解决问题,但只会增加问题。 When I now start my software, it will not stop, even when the problematic tab is not even visible (the tab is constructed, but is not visible). 现在,当我启动软件时,即使有问题的选项卡甚至不可见(该选项卡已构建,但也不可见),它也不会停止。 The relax method from MyVisRunner has not even been called in that case; 在这种情况下,甚至没有调用MyVisRunner的Relax方法。 the thread is not initialized anywhere else in the VisRunner class. 该线程未在VisRunner类中的其他任何地方初始化。 Commenting out the setRelaxer line will solve this additional problem (obviously keeping the original problem). 注释掉setRelaxer行将解决此附加问题(显然保留了原始问题)。

Update 2 更新2

I have solved the problem finally. 我终于解决了问题。 I didn't realize that when I set my own relaxer, there was already a relaxer running. 我没有意识到当我设置自己的放松器时,已经有一个放松器在运行。 I have adjusted the code to: 我已将代码调整为:

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

This has solved both the additional problem as well as my original one. 这解决了其他问题以及我原来的问题。

You should set the thread as a daemon thread: 您应该将线程设置为守护程序线程:

myThread.setDaemon(true);

A Virtual Machine will terminate if there are no more running non-daemon threads. 如果没有更多正在运行的非守护线程,则虚拟机将终止。


BTW you can add a WindowListener on your JFrame for windowClosing events. 顺便说一句,您可以在JFrame上添加一个WindowListener来处理windowClosing事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM