java - EventQueue.invokeLater() 有一些错误

标签 java swing nullpointerexception

运行此代码时一切正常,但是当我更改内部代码以与 EventQueue.invokeLater() 一起使用时,主要问题出现了

package dav.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JProgressBar;

public class SplashWindow extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private JProgressBar progressBar;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        //from here...
        final SplashWindow frame = new SplashWindow();                  frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        for (int i = 0; i < 100; i++) {
            frame.setProgress(i);
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
//to here...
    }

    /**
     * Create the frame.
     */
    public SplashWindow() {
        setUndecorated(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        JPanel panel = new JPanel();
        contentPane.add(panel, BorderLayout.CENTER);

        progressBar = new JProgressBar();
        progressBar.setMaximum(100);
        progressBar.setValue(0);
        progressBar.setForeground(Color.CYAN);

        panel.setBackground(Color.BLUE);
        GroupLayout gl_panel = new GroupLayout(panel);
        gl_panel.setHorizontalGroup(gl_panel.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_panel.createSequentialGroup().addContainerGap()

                        .addComponent(progressBar, GroupLayout.DEFAULT_SIZE, 420, Short.MAX_VALUE).addContainerGap()));
        gl_panel.setVerticalGroup(gl_panel.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_panel
                        .createSequentialGroup().addGap(245).addComponent(progressBar, GroupLayout.PREFERRED_SIZE,
                                GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(31, Short.MAX_VALUE)));
        panel.setLayout(gl_panel);

    }

    public void setProgress(int i) {
        progressBar.setValue(i);
        if (i+1>=progressBar.getMaximum()){
            dispose();}
    }
}

将主要方法更改为

public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
final SplashWindow frame = new SplashWindow();                  frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                    for (int i = 0; i < 100; i++) {
                        frame.setProgress(i);
                        try {
                            Thread.sleep(100);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

    }

没有异常(exception),但它没有按预期工作,而且众所周知,由于 EDT,使用 EventQueue 比在 main 方法中工作更可取。

但下面的工作。

final SplashWindow frame = new SplashWindow();
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        for (int i = 0; i < 100; i++) {
            frame.setProgress(i);
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

尽管进度条在某些时候变为空并且哎呀! NullPointerException 被抛出。如您所见,我正在制作自定义 SplashWindow 而不是内置的。需要帮助,请不要指出一些库。

最佳答案

EventQueue.invokeLater 没有错,关键在于您如何使用它。

这...

EventQueue.invokeLater(new Runnable() {
    public void run() {
        //...
    }
});

是说,在未来的某个时候,这样做。但是,您立即跟进......

for (int i = 0; i < 100; i++) {
    frame.setProgress(i);
    try {
        Thread.sleep(100);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

它可能会在 invokeLater 有机会运行之前执行。

一个总体上更好的解决方案是改用 SwingWorker 并在 EventQueue.invokeLater 中启动它,一旦您确保 UI 的状态已经建立。

请记住,Swing 不仅是单线程的,而且不是线程安全的。这意味着你不仅不应该阻塞主 UI 线程(即事件调度线程),也不应该从它的外部更新 UI 或它依赖的任何东西

参见 Worker Threads and SwingWorker了解更多详情

关于java - EventQueue.invokeLater() 有一些错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58193149/

相关文章:

java - 在具有操作和鼠标监听器的 GUI 中,未为 JTable 触发 MouseClicked

java - 如何实时获取jTextField的值?

java - 打包 JMeter Gui

android - 删除和添加 View NPE、蜂窝、android

java - 什么是NullPointerException,我该如何解决?

java - 将eclipse java项目转换为maven模块项目

java - 为什么 Java 中的 Number 类不是接口(interface)而不是抽象类?

java - 如何使用java代码在eclipse的控制台中插入值

java-如何确定不同类型服务器中特定类型处理的最佳线程数

java - 线程 "main"java.lang.NullPointerException 中出现异常,不知道我做错了什么