簡體   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