How to call SwingWorker.get () without GUI freezing?

I made a sample to find out the question:

public class Worker extends SwingWorker<Integer, Integer> { private GeneralUserInterface gui; public Worker(GeneralUserInterface gui){ this.gui = gui; } @Override protected Integer doInBackground() throws Exception { int someResultToReturn = 10; for(int i=0; i<100; i++){ Thread.sleep(50);//The Work publish(i+1);//calls process, which updates GUI } return someResultToReturn; } @Override protected void process(List<Integer> values) { for (Integer val : values) { gui.updateProgressBar(val); } } } private void jButtonDoWorkActionPerformed(java.awt.event.ActionEvent evt) { Worker worker = new Worker(this); worker.execute(); try { int resultToGet = worker.get();//Obviously freezes the GUI } catch (InterruptedException | ExecutionException ex) {} //NEXT LINE NEEDS THE RESULT TO CONTINUE } public void updateProgressBar(int value){ this.jProgressBar1.setValue(value); } 

As you might have guessed, calling worker.get () makes the user interface unresponsive, which is normal since it waits for the thread to finish. How is this problem usually resolved?

+4
source share
2 answers

How is this problem usually resolved?

Usually you override the Swingworker.done() method. Running on the GUI thread is executed when your background thread is completed. Then you can safely call get without blocking and do whatever you need.

Here is one way to do this:

 public class Worker extends SwingWorker<Integer, Integer> { private GeneralUserInterface gui; // omitted... @Override protected Integer doInBackground() throws Exception { int someResultToReturn = 10; for(int i=0; i<100; i++){ Thread.sleep(50);//The Work publish(i+1);//calls process, which updates GUI } return someResultToReturn; } // omitted... @Override protected void done() { try { int resultToGet = worker.get();//Obviously freezes the GUI } catch (InterruptedException | ExecutionException ex) {} //NEXT LINE NEEDS THE RESULT TO CONTINUE } } private void jButtonDoWorkActionPerformed(java.awt.event.ActionEvent evt) { Worker worker = new Worker(this); worker.execute(); } 

However, this may not be the most convenient design. I believe that it is best to use GUI material as an open class, and then create a working swing as a non-static inner class. Thus, the done method has easy access to all private GUI variables.

+5
source

The best solution is to provide your SwingWorker with an instance of the interface implemented by your GUI. Thus, your worker can update the graphical interface.

 public class GUI implements GUI_INTERFACE{ .... new foo(this); @Override public void INTERFACE_METHOD(Object info){ //Update Gui variables here. } } 

For your SwingWorker:

 class foo extends SwingWorker{ GUI_INTERFACE int public foo(GUI_INTERFACE bar){ int=bar } } 
0
source

Source: https://habr.com/ru/post/1446558/


All Articles