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
我省略了一些语法,但由于某种原因,最后没有调用startScanning()方法。将显示该对话框,但不会调用该方法。有人可以解释一下原因吗?
答案 0 :(得分:2)
我想,它与JOptionPane.showMessageDialog
有关。在程序进行之前,必须关闭MesageDialog 。如果您没有显示对话框的图形设备,它也可以抛出HeadlessException
。
检查所有打开的窗口,并为您的catch
阻止实施良好try
。
一个小例子程序,用于显示正在发生的事情:
public static void main(String[] args) {
JOptionPane.showMessageDialog(null, "Message");
System.out.println("done");
}
控制台输出done
仅在您拥有图形设备时才出现,并且仅在关闭对话窗口后显示。
答案 1 :(得分:1)
一些观察结果:
startScanning()
,第一次在Swing事件线程上,所有其他递归时间都离开线程,这有点麻烦。我找到了它所属的位置并在该线程环境中(在EDT上或在其上)调用它,并且仅在该线程环境中调用它。例如
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;
}
}