java - 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)
解决方案
请注意,错误不仅仅是由图像引起的。
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的信息
推荐阅读
- javascript - 如何在另一个网页中打开网页而不向外界透露
- android - 如何在 android oreo 的锁定屏幕上显示音乐播放器之类的通知?
- coffeescript - Coffeescript 将数组转换为字典,其中字典将具有多个值
- javascript - 在父级 HTML 字符串之间的特定点附加 DOM 元素
- deep-learning - Darkflow 已完美安装和导入。但是 TFNet 不是从 darkflow.net.build 导入的
- mongodb - 已解决:如何创建没有卷的 Mongodb docker 容器
- python - 如何使用模板标签在 django 表单上填充“占位符”
- java - java.sql.SQLSyntaxErrorException:“字段列表”中的未知列“column_name”-实体中的映射与数据库中的映射相同
- mariadb - 为现有的 mariadb 数据库创建集群
- android - 为什么此测试会触发 Robolectric 委托运行程序 RuntimeException?