简体   繁体   中英

Java Program is not Calling Method

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:

  • Again as per my comments, it's impossible to know with confidence what is wrong with your program given the information provided. Consider telling and showing more, in particular a minimal example program .
  • I do see though that you're not observing Swing threading rules correctly. For instance you are most definitely calling JOptionPane off of the Swing event thread, something you should never do. You're also calling the method 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.
  • Myself, I'd make my SwingWorker tell me if it finished appropriately or not, and again this can be done easily by having doInBackground return a value, or you could set a bound property of your worker class.
  • I'm a big fan of using PropertyChangeListeners with my SwingWorkers, since this allows better observance of the Law of Demeter -- keep coupling as low as possible.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM