public void startScanning() {
// Check if there is a webcam available
if (cameraView.getWebcamPanel() == null) {
return;
}
// Make sure the webcam is not null
if (cameraView.getWebcam() == null) {
return;
}
if (!cameraView.getWebcam().isOpen()) {
cameraView.getWebcam().open();
}
// Make sure the webcam is open
if (cameraView.getWebcam().isOpen()) {
// Create a SwingWorker thread to run in the background
worker = new SwingWorker<Void, Void>() {
try {
qrResult = new MultiFormatReader().decode(bitmap);
//System.out.println("qrResults: " + qrResult);
try {
// new error handling
int length = qrResult.getText().length();
if(length != 23){
JOptionPane.showMessageDialog(null, "Username and password is correct");
startScanning();
}
// end of error handling
I omitted some of the syntax, but for some reason the startScanning() method is not called at the very end. The dialog box is shown, but the method isn't called. Can someone please explain why?
I suppose, it's related to JOptionPane.showMessageDialog
. The MesageDialog has to be closed before the program proceeds. And it can also throw an HeadlessException
if you don't have a graphics device to show the dialog at.
Check any open windows and implement a good catch
to your try
block.
A small example program to show what's happening:
public static void main(String[] args) {
JOptionPane.showMessageDialog(null, "Message");
System.out.println("done");
}
The console output done
will only appear, if you have a graphics device, and only after you closed the dialog window.
Some observations:
startScanning()
recursively, the first time on the Swing event thread, all the other recursive times off of the thread and this smells of trouble. I'd find out where it belongs and call it in that thread environment (on or off the EDT) and only that thread environment. For example
import java.awt.Component;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
@SuppressWarnings("serial")
public class FooGui extends JPanel {
// create my button's Action
private StartScanningAction action = new StartScanningAction("Start Scanning", this);
private JButton button = new JButton(action); // pass Action into button's constructor
// this is spinner is used just to show passing information into the SwingWorker
private JSpinner spinner = new JSpinner(new SpinnerNumberModel(25, 0, 50, 1));
// JTextField to show results from SwingWorker
private JTextField resultField = new JTextField(5);
public FooGui() {
resultField.setFocusable(false);
add(spinner);
add(button);
add(resultField);
}
// override method so that the JPanel controls whether its components are enabled or not
@Override
public void setEnabled(boolean enabled) {
button.setEnabled(enabled);
spinner.setEnabled(enabled);
super.setEnabled(enabled);
}
// get value so you can pass it into the Swingworker
public int getSpinnerValue() {
return (Integer) spinner.getValue();
}
// allow outside classes to set the resultField JTextField
public void setResultText(String text) {
resultField.setText(text);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("FooGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FooGui());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
// Start our GUI in a Swing Thread-safe way
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// JButton's Action
@SuppressWarnings("serial")
class StartScanningAction extends AbstractAction {
public static final int MINIMAL_VALUE = 50;
private FooGui fooGui; // the main GUI
private Component sourceComp; // the JButton
private int initValue; // value from the spinner
private JDialog dialog; // modal dialog to hold our JProgressBar
public StartScanningAction(String name, FooGui fooGui) {
super(name);
this.fooGui = fooGui;
}
@Override
public void actionPerformed(ActionEvent e) {
this.sourceComp = (Component) e.getSource();
// get the top-level window that holds our JButton
Window win = SwingUtilities.getWindowAncestor(sourceComp);
// create our JDialog in a lazy way
if (dialog == null) {
// JProgressBar to show in dialog when worker is working
JProgressBar progBar = new JProgressBar();
// if we plan to set the worker's progress property, then the dialog would not be indeterminate
progBar.setIndeterminate(true);
// pass win into dialog. Make it modal
dialog = new JDialog(win, "Awaiting Worker", ModalityType.APPLICATION_MODAL);
dialog.add(progBar);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
// disable the main GUI
fooGui.setEnabled(false);
// extract info from the main GUI
initValue = fooGui.getSpinnerValue();
// call the method that gets our worker going
startScanning(initValue);
}
// method that gets worker going. This is called on the EDT
private void startScanning(int initValue) {
// create a worker object
StartScanningWorker worker = new StartScanningWorker(initValue);
// add property change listener to the worker
worker.addPropertyChangeListener(new PcListener());
// execute the worker
worker.execute();
// show our dialog. this freezes program flow so must be done last
dialog.setVisible(true);
}
// listen for state changes to the worker. This is done on the EDT
private class PcListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// if the worker is done working
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
dialog.dispose(); // get rid of the modal dialog
// extract worker
StartScanningWorker worker = (StartScanningWorker) evt.getSource();
try {
// deal with any exceptions that occurred during worker's run
worker.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
return; // this one's a bad exception
}
// get worker's value and check if it is adequate
int someValue = worker.getSomeValue();
if (someValue < MINIMAL_VALUE) {
// our worker failed -- display a JOptionPane. We're on the EDT so this thread is OK for this
String message = String.format("someValue is %d which is less than the "
+ "minimal value, %d. To re-run worker", someValue, MINIMAL_VALUE);
String title = "Some Value Not High Enough";
int messageType = JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(sourceComp, message, title, messageType);
// recursive call made on the EDT. Be careful doing this.
startScanning(initValue);
} else {
// else the worker's result was good. Display the results and re-enable the GUI
fooGui.setResultText(String.valueOf(someValue));
fooGui.setEnabled(true);
}
}
}
}
}
// worker that doesn't do anything important
class StartScanningWorker extends SwingWorker<Void, Void> {
private static final long SLEEP_TIME = 2 * 1000;
public static final String SOME_VALUE = "some value";
private int someValue;
public StartScanningWorker(int someInitialValue) {
// initialize the worker with a value from the GUI
this.someValue = someInitialValue;
}
public int getSomeValue() {
return someValue;
}
// if I want someValue to be a bound property. Not necessary in this example
public void setSomeValue(int someValue) {
int oldValue = this.someValue;
this.someValue = someValue;
firePropertyChange(SOME_VALUE, oldValue, someValue);
}
@Override
protected Void doInBackground() throws Exception {
// simulate along-running process
Thread.sleep(SLEEP_TIME);
// get a random value
int value = (int) (100 * Math.random()) + someValue;
setSomeValue(value);
// end the worker
return null;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.