I've already browsed many threads on this topic, but nothing seems to fit my specific situation.
I have a swing application which analyzes QR-Codes, extracts the found loginNames and makes DB calls to fetch data for that user. To make sure the capture of the QR-Codes can be canceled and my application is still accessible while capturing, I used a SwingWorker for this purpose. Everything works fine so far, I've included a PropertyChangeListener so the application knows when my SwingWorker successfully read a code. But since I don't want to have the PropertyChangeListener as a nested class within my mainClass (to keep it well structured), I've created a new class for it outside. Now I want to return to my main class from this PropertyChangeListener class to switch to the appropriate panel which displays the fetched data. I have different codes which can be read, so depending on the code I have different panels to switch to (so I can't do a static switch to the same panel over and over again). So how can I delegate the PropertyChangeListener to give the control back to my EDT ? I've tried using wait() and notify() to let my EDT know the SwingWorker finished. But obviously wait() blocks my EDT and the use of SwingWorker is pointless.
I hope I could explain my problem in enough detail, and some of you have a good idea to deal with this. For any code snippets please ask, I'll then add the necessary ones. But since my project is a bit more complex I'll just post what is asked for.
Thanks in advance for any help :)
EDIT: Here is a code excerpt to illustrate what my SwingWorker is doing.
SwingWorker class:
public class CodeDetector extends SwingWorker<byte[], String> {
String s; // read String
byte[] completeCode; // byte[] which is returned by doInBackground()
BufferedImage resizedImg;
IplImage img;
JLabel labelForStream;
JLabel result;
FrameGrabber grabber = new VideoInputFrameGrabber(); // using JavaCV.
public CodeDetector(JLabel labelForStream, JLabel result) {
this.labelForStream = labelForStream;
this.resultLabel = result;
}
@Override
protected byte[] doInBackground() throws Exception {
try {
grabber.start(); //
while (true) {
// End if current thread was canceled.
if (Thread.currentThread().isInterrupted()) {
return null;
}
// Grab each image, save it, scan for code and display it.
img = grabber.grab();
resizedImg = // resizing image to fit labelForStream.
// save resizedImg to file
// read barcode from saved file
if (isBadgeCode(tmp) || isDeviceCode(tmp)) {
s = tmp;
} else {
continue;
}
break;
} catch (NotFoundException e) {
// Code could not be encoded yet.
}
...
// end worker after timeout
// show image on window
if (img != null) {
labelForStream.setIcon(new ImageIcon(resizedImg));
}
}
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage() + " - " + e.getStackTrace() + " - " + e.getClass());
}
return s != null ? s.getBytes() : null;
}
@Override
protected void done() {
try {
completeCode = get();
if (completeCode != null) {
String code = new String(completeCode);
if (isOtherCode(code)) {
resultLabel.setText(code);
} else if (isUsernameCode(code)) {
// Cut userName from read code (if previously verified) and set label text.
resultLabel.setText(verify(code, true) ? code.split(":")[0] : null);
}
} else {
resultLabel.setText(null);
}
resultLabel.setVisible(true);
resultLabel.updateUI();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (CancellationException e) {
return;
} catch (Exception e) {
e.printStackTrace();
}
}
As this SwingWorker doesn't have references to any panels, even though the done()-method is done in EDT, I need to somehow notify my mainClass that a code has been read successfully and that it can change the panl now according to the specific code.
Hope this clears things up a bit.