繁体   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

我省略了一些语法,但是由于某种原因,并未在最后调用startScanning()方法。 显示对话框,但未调用该方法。 有人可以解释为什么吗?

我想这与JOptionPane.showMessageDialog有关。 在程序继续之前,必须关闭 MesageDialog。 如果您没有用于显示对话框的图形设备,它也可能引发HeadlessException

检查所有打开的窗口,并对您的try块实施良好的catch

一个小的示例程序来显示正在发生的事情:

public static void main(String[] args) {
    JOptionPane.showMessageDialog(null, "Message");
    System.out.println("done");
}

仅当您具有图形设备时,并且仅在关闭对话框窗口之后,控制台输出done才会显示。

一些观察:

  • 同样,根据我的评论,鉴于所提供的信息,无法自信地知道您的程序出了什么问题。 考虑讲更多的内容,特别是一个最小的示例程序
  • 我确实看到您没有正确遵守Swing线程规则。 例如,您绝对可以在Swing事件线程之外调用JOptionPane,这是您永远都不应做的事情。 您还递归调用方法startScanning() ,这是在Swing事件线程上的第一次,所有其他递归时间都在线程之外,这很麻烦。 我会找出它所属的位置,并在该线程环境(在EDT上或下)和仅在该线程环境中调用它。
  • 我自己,我想让SwingWorker告诉我它是否正确完成,并且可以通过让doInBackground返回一个值来轻松完成此操作,或者可以设置worker类的绑定属性。
  • 我非常喜欢将PropertyChangeListeners与我的SwingWorkers一起使用,因为这可以更好地遵守Demeter定律-保持尽可能低的耦合。

例如

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