lochi
lochi

Reputation: 880

Swing Worker Delay

I have a button click event that will fire a swing worker thread which in return fire another thread to do a long calculation including writing a file. Then this file is read to draw some graphics. However drawing part never happens if i don't add a delay in between.. (It says file not found although the file is there..What is the better way to fix this without adding a delay..

 private void buttonFragmentActionPerformed(java.awt.event.ActionEvent evt) {                                               
    try
    {
        ESIPlusFragmenterWorker epfw = new ESIPlusFragmenterWorker(10, sdfFile, cidSpectrum);
        epfw.execute();

        Thread.sleep(1000);

        holder.molTable1.drawMolViewPanel(currDir+sep+"esiFragments"+sep+"esiFrag.sdf");
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

Swing Worker

public class ESIPlusFragmenterWorker extends SwingWorker<Void, Void>{

int mzppm_;
String SDF_;
String spectrum_;
Double mion_;
MolTable holder_;

ESIPlusFragmenterWorker(int mzppm, String SDF, String spectrum)
{
    mzppm_ = mzppm;
    SDF_ = SDF;
    spectrum_ = spectrum;
}

@Override
protected Void doInBackground() {
    try
    {
    Molecule mol;
    MolImporter importer = new MolImporter(SDF_);
    ExecutorService te = Executors.newFixedThreadPool(1);
    while ((mol  = importer.read()) != null) 
    {
     Runnable epf = new ESIPlusFragmenter(mol, spectrum_, mzppm_);
     Thread t = new Thread(epf);
     te.execute(epf);
    }
    importer.close();
    te.awaitTermination(10, TimeUnit.MINUTES);
    }
    catch (Exception e)
    {
      //  
    }
    finally
    {
        return null;
    }
}


@Override
protected void done() {
    try {
        //
    } catch (Exception e) {
        //e.printStackTrace();
    }
}

}

Upvotes: 2

Views: 998

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285430

Never, never, never call Thread.sleep(...) on the EDT as this will put your entire GUI to sleep. And besides, what if you estimate wrong, and the background process takes longer than your sleep delay time?

One possible solution is to add a PropertyChangeListener to the SwingWorker and listen on the "state" property for the SwingWorker.StateValue to be SwingWorker.StateValue.DONE, then do your drawing.

e.g.

private void buttonFragmentActionPerformed(java.awt.event.ActionEvent evt) {
  try {
     ESIPlusFragmenterWorker epfw = new ESIPlusFragmenterWorker(10,
           sdfFile, cidSpectrum);
     epfw.addPropertyChangeListener(new PropertyChangeListener() {

        @Override
        public void propertyChange(PropertyChangeEvent pcEvt) {
           if ("state".equals(pcEvt.getPropertyName())) {
              if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
                 holder.molTable1.drawMolViewPanel(currDir + sep
                       + "esiFragments" + sep + "esiFrag.sdf");
              }
           }
        }
     });
     epfw.execute();

So what this does is waits until the SwingWorker has completed its business before calling the code inside of the listener.

Another option is to call your holder.molTable1.drawMolViewPanel inside of the SwingWorker's done() method, and this will work too, but by doing it as noted above with a PropertyChangeListener, the SwingWorker doesn't have to have any knowledge about the code called in the listener (as opposed to using SwingWorker's done() method), and this may allow for looser coupling.

Upvotes: 2

Related Questions