Search code examples
javaeclipseswingswingworkerwindowbuilder

Java swingworker() process() not getting called


I am using swingworker() to create a background thread that publishes results and GUI should be updated through process(). But process() never gets called:

public class comm {
    protected Shell shldPrinter;
    private Text v1time;
    private static Text cTemp1;
    static boolean control1 = false; 

    /**
     * Launch the application.
     * @param args
     */
    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                 try {
                    new comm();  //create the user interface named window
                    //window.open();             //invoke open() function
                } catch (Exception e) {
                    e.printStackTrace();
                }
             }
          });
    }

    /**
     * Open the window.
     */
    public comm() {
        this.open();
    }
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shldPrinter.open();
        shldPrinter.layout();
        while (!shldPrinter.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    private void start() {
        SwingWorker<Boolean,String> worker = new SwingWorker<Boolean,String> () {
            //@Override
            protected Boolean doInBackground() throws Exception {
                   while(control1) {
                       curtemp1++;
                       publish(Double.toString(curtemp1));
                       System.out.println(curtemp1);
                       try {
                           Thread.sleep(500);  // milliseconds
                        } catch (InterruptedException ex) {}
                   }

                return true;
            }

            protected void process(List<String> chunks) {
                cTemp1.setText("chunks.get(chunks.size()-1)");
            }

        };
        worker.execute();
    }

    /**
     * Create contents of the window.
     */
    protected void createContents() {
        shldPrinter = new Shell();
        shldPrinter.setSize(490, 299);
        shldPrinter.setText("Robogel Temp Control");

        final Button btnCln1 = new Button(shldPrinter, SWT.CHECK);
        btnCln1.addSelectionListener(new SelectionAdapter() {
            @Override

            public void widgetSelected(SelectionEvent e) {
                control1 = btnCln1.getSelection();
                if(control1)
                    start();
            }
        });
        btnCln1.setBounds(22, 51, 69, 16);
        btnCln1.setText("Valve 1");

        //create text box for valve 1 timing
        v1time = new Text(shldPrinter, SWT.BORDER | SWT.CENTER);
        v1time.addFocusListener(new FocusAdapter() {
            @Override
            //when cursor moves away from text box
            public void focusLost(FocusEvent e) {
                reftemp1 = Double.parseDouble(v1time.getText()); // get time in ascii format and convert it into int
            }
        });
        v1time.setText("25");
        v1time.setBounds(97, 49, 51, 21);

        cTemp1 = new Text(shldPrinter, SWT.BORDER | SWT.CENTER);
        cTemp1.setEditable(false);
        cTemp1.setText(Double.toString(curtemp1));
        cTemp1.setBounds(203, 49, 51, 21);
    }
}

instead when GUI is closed, following error appears:

Exception in thread "AWT-EventQueue-0" org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:4397)
at org.eclipse.swt.SWT.error(SWT.java:4312)
at org.eclipse.swt.SWT.error(SWT.java:4283)
at org.eclipse.swt.widgets.Widget.error(Widget.java:472)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:344)
at org.eclipse.swt.widgets.Text.setText(Text.java:2240)
at comm$2.process(comm.java:172)
at javax.swing.SwingWorker$3.run(Unknown Source)
at sun.swing.AccumulativeRunnable.run(Unknown Source)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unknown Source)
at sun.swing.AccumulativeRunnable.run(Unknown Source)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(Unknown Source)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

I have read a lot of forums but nothing really helped. Have tried calling done() but even that does not get called.


Solution

  • You mixing the Swing EDT and the SWT Thread. This will result in Exceptions, since SWT checks every call if it was made in the SWT Thread. Remove from your code: Swing

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
             try {
                new comm();  //create the user interface named window
                //window.open();             //invoke open() function
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
      });
    

    You only need this in a swing environment because swing starts the EDT. In SWT, the thread which creates the Display will be the EDT. New Version:

      new comm();  //create the user interface named window
    

    Now to perform stuff in the background you can use the usual java mechanism (concurrent etc.) but DON'T use Swing stuff, it only makes thins very complicated. Important is, that after the background work is complete you synchronize back to the SWT EDT with Display#asyncExec here is an example

    I would suggest to rewrite your example without any swing code and repost any problems in a new question. (Very weird stuff is going on otherwise and its difficult to tell what the problem is from my point of view).