java - 线程 "AWT-EventQueue-0"java.lang.NullPointerException 中出现异常(面板在完全加载之前显示?)

标签 java multithreading swing splash-screen

当我在 JFrame 上过快地按下 JButton 时,我会收到此错误,因此如果编译程序和按下按钮之间有轻微的延迟,它就会起作用。我尝试制作一个启动屏幕/加载屏幕,看看我是否给程序更多的时间来编译它是否可以在没有延迟的情况下工作,但到目前为止,如果按得太快它仍然会崩溃。我想知道是否有一种方法可以预加载它,这样在按下按钮之前不需要有延迟,这样错误就不会存在,谢谢!

(列出了相关的代码片段,但由于整个包有几千行,我不会将所有代码都放在这里)

这是在主方法中运行的。

Panels panel = new Panels(); 
panel.getWindow();

这是在一个单独的“Window”类中

public Window(JPanel panel)
{
    super("Knight Quest");
    //loading screen
    JWindow window = new JWindow();
    window.getContentPane().add(new JLabel("Loading..."));
    window.getContentPane().add(
            new JLabel("", new ImageIcon(getClass().getResource("loading.gif")), SwingConstants.CENTER));
    window.setBounds(600, 300, 400, 300);
    window.setVisible(true);
    try 
    {
        Thread.sleep(2500);
    } catch (InterruptedException e) 
    {
        e.printStackTrace();
    }
    window.setVisible(false);
    //end of loading screen
    setLayout(new BorderLayout());
    add(panel, BorderLayout.CENTER);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(600,550);
    setLocation(525, 225);
    setVisible(true);;

}

这是在面板类的顶部

private Window window = new Window(main());     

这是启动程序的 main() JPanel(只是向 JPanel 添加内容)

public JPanel main()
{
    JPanel main = new JPanel();
    check = "main";
    main.setBackground(lightGrey);
    Handler handles = new Handler();

    one = new JButton("Start ");
    two = new JButton("Patch Notes");
    three = new JButton("Exit   ");

    one.addActionListener(handles);
    two.addActionListener(handles);
    three.addActionListener(handles);

    image =  new ImageIcon(getClass().getResource("templar.jpg"));

    JLabel title = new JLabel("Knight Quest");
    title.setFont(new Font("Serif", Font.PLAIN, 45));
    JLabel mainPic = new JLabel(image);
    JLabel versionNum = new JLabel("v1.1.0");
    JLabel credit = new JLabel("Created and developed by Joseph Torres");

    Box panel = Box.createVerticalBox();
    panel.add(title);
    panel.add(Box.createRigidArea(new Dimension(50, 50)));
    panel.add(one);
    panel.add(Box.createRigidArea(new Dimension(50,50)));
    panel.add(two);
    panel.add(Box.createRigidArea(new Dimension(50,50)));
    panel.add(three);
    panel.add(Box.createRigidArea(new Dimension(50,150)));
    panel.add(versionNum);
    panel.add(credit);

    main.add(panel);
    main.add(mainPic);
    return main;
}

并且空指针异常是在

处生成的
private class Handler implements ActionListener, KeyListener
{
    public void actionPerformed(ActionEvent event)
    {
        //First Button
        if(event.getSource() == one)
        {
            if(check.equals("main"))
            {
                window.setPanel(prologue());
            }
                    }
            }
     }

最后,setPanel 是 windows 类中的一个方法

public void setPanel(final JPanel panel) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            getContentPane().removeAll();
            add(panel, BorderLayout.CENTER);
            if(Panels.sizeCheck != 1)
            {
                setSize(600, 550);
                setLocation(525, 225);
            }
            else
            {
                setSize(1000, 600);
                setLocation(300, 100);
            }
            revalidate();
            repaint();
        }
    });
}

这已经是一堵巨大的文字墙,但这些都是我认为相关的重要部分。代码本身可以工作,这只是加载速度太快或我可能忽略的问题之一。如果您需要更多代码或完整程序,请告诉我,我很乐意发布。谢谢!

编辑:堆栈跟踪

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Panels$Handler.actionPerformed(Panels.java:1228)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

最佳答案

您不应该使用Thread.sleep()来延迟面板的加载。这会阻塞 UI 线程并且不会执行您想要的操作。相反,请使用 Swing Timer:

public Window(final JPanel panel)
{
    super("Knight Quest");
    //loading screen
    final JWindow window = new JWindow();
    window.getContentPane().add(new JLabel("Loading..."));
    window.getContentPane().add(
            new JLabel("", new ImageIcon(getClass().getResource("loading.gif")), SwingConstants.CENTER));
    window.setBounds(600, 300, 400, 300);
    window.setVisible(true);
    javax.swing.Timer timer = new javax.swing.Timer(2500,
        new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                window.setVisible(false);
                setLayout(new BorderLayout());
                add(panel, BorderLayout.CENTER);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                setSize(600,550);
                setLocation(525, 225);
                setVisible(true);
            }
        }
    );
    timer.setRepeats(false);
    timer.start();
}

编辑:如果启动屏幕的唯一原因是为 window 分配一个完成的机会,那么有一个简单的方法可以消除这种情况:单独构造 Window 面板显示的对象。你可以这样做:

public Window() {
    super("Knight Quest");
}

public void display(JPanel panel) {
    setLayout(new BorderLayout());
    add(panel, BorderLayout.CENTER);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(600,550);
    setLocation(525, 225);
    setVisible(true);
}

然后在 Panels 类的顶部,替换这一行:

private Window window = new Window(main());

有一个简单的声明:

private Window window;

并将赋值移至 Panels 的构造函数中:

public Panels() {
    // . . . other constructor stuff (if any)

    window = new Window();
    window.display(main());
}

关于java - 线程 "AWT-EventQueue-0"java.lang.NullPointerException 中出现异常(面板在完全加载之前显示?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23724857/

相关文章:

java - 多个线程之间共享和锁定固定数量的资源

java - 大数乘法算法并不总是有效

java - Spring 和 Hibernate 配置错误无法从 URL 位置导入 bean 定义

java - 使用 gradle 依赖于 Java 9 Module System 库中的遗留 jar

c++ - 返回值寄存器和析构函数调用顺序

java - 图标处理抛出 NullPointerException

java - ExceptionMapper 实体似乎被 Quarkus 包裹

python - 使用 python 的网络服务器

java - 在带有 JFrame 表单的 Netbeans derby 中使用带有 WHERE 子句的 SELECT 语句

java - JPanel按钮等