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

StackOverflow https://stackoverflow.com/questions/15084387

  •  11-03-2022
  •  | 
  •  

Question

I have an application that uses a JTabbedPane to show several different tabs. 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. 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).

I prefer not to use the System.exit() method to close my application, but rather stop all threads and dispose all windows. 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(). Neither had the expected result. The removeAll() even had the opposite result. 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).

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.

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. 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:

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; the thread is not initialized anywhere else in the VisRunner class. Commenting out the setRelaxer line will solve this additional problem (obviously keeping the original problem).

Update 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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top