简体   繁体   English

Java程序不是调用方法

[英]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. 我省略了一些语法,但是由于某种原因,并未在最后调用startScanning()方法。 The dialog box is shown, but the method isn't called. 显示对话框,但未调用该方法。 Can someone please explain why? 有人可以解释为什么吗?

I suppose, it's related to JOptionPane.showMessageDialog . 我想这与JOptionPane.showMessageDialog有关。 The MesageDialog has to be closed before the program proceeds. 在程序继续之前,必须关闭 MesageDialog。 And it can also throw an HeadlessException if you don't have a graphics device to show the dialog at. 如果您没有用于显示对话框的图形设备,它也可能引发HeadlessException

Check any open windows and implement a good catch to your try block. 检查所有打开的窗口,并对您的try块实施良好的catch

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. 仅当您具有图形设备时,并且仅在关闭对话框窗口之后,控制台输出done才会显示。

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. 我确实看到您没有正确遵守Swing线程规则。 For instance you are most definitely calling JOptionPane off of the Swing event thread, something you should never do. 例如,您绝对可以在Swing事件线程之外调用JOptionPane,这是您永远都不应做的事情。 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. 您还递归调用方法startScanning() ,这是在Swing事件线程上的第一次,所有其他递归时间都在线程之外,这很麻烦。 I'd find out where it belongs and call it in that thread environment (on or off the EDT) and only that thread environment. 我会找出它所属的位置,并在该线程环境(在EDT上或下)和仅在该线程环境中调用它。
  • 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. 我自己,我想让SwingWorker告诉我它是否正确完成,并且可以通过让doInBackground返回一个值来轻松完成此操作,或者可以设置worker类的绑定属性。
  • 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. 我非常喜欢将PropertyChangeListeners与我的SwingWorkers一起使用,因为这可以更好地遵守Demeter定律-保持尽可能低的耦合。

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;
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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