首页 > 解决方案 > java - 如何在启动时自动执行Java应用程序中的方法?

问题描述

我正在构建一个小型 Java 应用程序来从 USB 摄像头加载图像或在找不到 USB 摄像头时显示错误消息(图像)。应用程序需要自动加载并启动“CaptureImage()”,但在“CaptureImage()”方法下出现 NullPointerException 错误。

如果我通过单击 gui 的按钮调用“CaptureImage()”(而不是尝试通过启动线程在“initialize()”中启动它),那么它可以正常工作。任何有关如何正确处理的指导将不胜感激。


public class WebcamCapture_gui {
    
    JFrame frmWebcamCapture_gui;
    static Canvas canvas = new Canvas();
    JPanel panel = new JPanel();
    static Image notFound = null;
    static boolean running = true;

    
    public static void main(String[] args) {
        
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    WebcamCapture_gui window = new WebcamCapture_gui();
                    window.frmWebcamCapture_gui.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    public WebcamCapture_gui() throws IOException {
        initialize();
    }


    private void initialize() {

        JButton btnNewButton = new JButton("OK", new ImageIcon(WebcamCapture_gui.class.getResource("/resources/ok-32.png")));
        btnNewButton.setFont(new Font("Lucida Grande", Font.BOLD, 16));
        btnNewButton.setMnemonic('o');
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                
                CaptureImage();
            }
        });
        btnNewButton.setBounds(918, 573, 156, 83);
        
        canvas.setBounds(6, 6, 1052, 547);
        
        frmWebcamCapture_gui = new JFrame();
        frmWebcamCapture_gui.setResizable(false);
        frmWebcamCapture_gui.setUndecorated(true);
        frmWebcamCapture_gui.setTitle("Camera Test");
        frmWebcamCapture_gui.setSize(1080, 662);
        frmWebcamCapture_gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmWebcamCapture_gui.getContentPane().setLayout(null);
        
        panel.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
        panel.setBounds(6, 6, 1068, 563);
        panel.setLayout(null);
        panel.add(canvas);
        frmWebcamCapture_gui.getContentPane().add(panel);
        frmWebcamCapture_gui.getContentPane().add(btnNewButton);
        
        File classPathInput = new File(WebcamCapture_gui.class.getResource("/resources/USB_not_found.png").getFile());
        try {
            notFound = ImageIO.read(classPathInput);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        /*
        *  If I remove this Thread start and use the button to call 'CaptureImage()' instead, then the images will load and no NPE.
        */
        Thread t1 = new Thread(new thread1());
        
        t1.start();
        
        try { 
            t1.join();
        } catch (Exception e1) {
            System.out.println(e1);
        }
    }
    
    
    public static class thread1 implements Runnable {
        @Override
        public void run() {
            
            CaptureImage();
            
        }
    }

    
    public static void CaptureImage() {
        
        Graphics g = canvas.getGraphics();
        
        Webcam webcam = Webcam.getDefault();
        
        if (webcam != null) {
            webcam.open();
            g.drawImage(webcam.getImage(), 0, 0, 1060, 554, null);
            webcam.close();
        } else {
            g.drawImage(notFound, 0, 0, 1060, 547, null);
        }
    }
}

堆栈跟踪:

javax.imageio.IIOException: Can't read input file!
    at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1308)
    at webcamCapture.WebcamCapture_gui.initialize(WebcamCapture_gui.java:80)
    at webcamCapture.WebcamCapture_gui.<init>(WebcamCapture_gui.java:44)
    at webcamCapture.WebcamCapture_gui$1.run(WebcamCapture_gui.java:34)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
[Thread-0] INFO com.github.sarxos.webcam.Webcam - WebcamDefaultDriver capture driver will be used
[Thread-0] WARN com.github.sarxos.webcam.Webcam - No webcam has been detected!
Exception in thread "Thread-0" java.lang.NullPointerException: Cannot invoke "java.awt.Graphics.drawImage(java.awt.Image, int, int, int, int, java.awt.image.ImageObserver)" because "g" is null
    at webcamCapture.WebcamCapture_gui.CaptureImage(WebcamCapture_gui.java:120)
    at webcamCapture.WebcamCapture_gui$thread1.run(WebcamCapture_gui.java:102)
    at java.base/java.lang.Thread.run(Thread.java:832)

标签: java

解决方案


请注意,错误不仅仅是由图像引起的。

Exception in thread "Thread-0" java.lang.NullPointerException: Cannot invoke "java.awt.Graphics.drawImage(java.awt.Image, int, int, int, int, java.awt.image.ImageObserver)" because "g" is null
    at webcamCapture.WebcamCapture_gui.CaptureImage(WebcamCapture_gui.java:120)
    at webcamCapture.WebcamCapture_gui$thread1.run(WebcamCapture_gui.java:102)
    at java.base/java.lang.Thread.run(Thread.java:832)

当您立即启动线程时,画布图形可能尚未初始化并且调用该drawImage方法会引发 NPE。

为了规避 NPE,您可以替换

t1.start();

SwingUtilities.invokeLater(t1); 

另一个“肮脏”的解决方法是离开 t1.start(); 但通过添加 frmWebcamCapture_gui.setVisible(true) 来强制应用加载其组件;在thread1的run方法中

  public class thread1 implements Runnable {
    @Override
    public void run() {
     frmWebcamCapture_gui.setVisible(true);
      CaptureImage();
    }
  }

这主要是为了演示和解释的目的,所以我建议你采用第一种使用方法SwingUtilities您可以在这篇文章文档中阅读更多关于 SwingUtilities.invokeLater的信息


推荐阅读