Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
“线程中的异常”;AWT-EventQueue-0“;java.lang.NullPointerException(面板在完全加载之前显示?)_Java_Multithreading_Swing_Splash Screen - Fatal编程技术网

“线程中的异常”;AWT-EventQueue-0“;java.lang.NullPointerException(面板在完全加载之前显示?)

“线程中的异常”;AWT-EventQueue-0“;java.lang.NullPointerException(面板在完全加载之前显示?),java,multithreading,swing,splash-screen,Java,Multithreading,Swing,Splash Screen,当我在JFrame上过快地按下JButton时,我就遇到了这个错误,因此如果在编译程序和按下按钮之间有一点延迟,它就会工作。我试着做一个启动屏幕/加载屏幕,看看我是否给程序更多的时间来编译它是否能在没有延迟的情况下工作,但到目前为止,如果按下得太快,它仍然会崩溃。我想知道是否有一种方法可以预加载它,这样在按下按钮之前就不需要延迟,这样错误就不会存在了,谢谢 (列出了相关的代码片段,但由于整个程序包只有几千行,因此我不打算将其全部放在这里) 这是在main方法中运行的 Panels panel =

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

(列出了相关的代码片段,但由于整个程序包只有几千行,因此我不打算将其全部放在这里)

这是在main方法中运行的

Panels panel = new Panels(); 
panel.getWindow();
这是在一个单独的“窗口”类中

这是在面板类的顶部

private Window window = new Window(main());     
这是启动程序的main()JPanel(只是向JPanel添加内容)

而nullpointerexception是在

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
计时器

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();
}
编辑:如果启动屏幕的唯一原因是给
窗口
分配一个完成的机会,那么有一个简单的方法来消除这一点:将
窗口
对象的构造与面板的显示分开。你可以这样做:

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);
}
然后在
面板的顶部
类中,替换此行:

private Window window = new Window(main());
用一个简单的声明:

private Window window;
并将赋值移动到
面板的构造函数中

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

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

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

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();
}
编辑:如果启动屏幕的唯一原因是给
窗口
分配一个完成的机会,那么有一个简单的方法来消除这一点:将
窗口
对象的构造与面板的显示分开。你可以这样做:

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);
}
然后在
面板的顶部
类中,替换此行:

private Window window = new Window(main());
用一个简单的声明:

private Window window;
并将赋值移动到
面板的构造函数中

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

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

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

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();
}
编辑:如果启动屏幕的唯一原因是给
窗口
分配一个完成的机会,那么有一个简单的方法来消除这一点:将
窗口
对象的构造与面板的显示分开。你可以这样做:

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);
}
然后在
面板的顶部
类中,替换此行:

private Window window = new Window(main());
用一个简单的声明:

private Window window;
并将赋值移动到
面板的构造函数中

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

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

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

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();
}
编辑:如果启动屏幕的唯一原因是给
窗口
分配一个完成的机会,那么有一个简单的方法来消除这一点:将
窗口
对象的构造与面板的显示分开。你可以这样做:

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);
}
然后在
面板的顶部
类中,替换此行:

private Window window = new Window(main());
用一个简单的声明:

private Window window;
并将赋值移动到
面板的构造函数中

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

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

您需要延迟以避免出现
NullPointerException
,这意味着您的代码中存在排序错误。看起来您只是在设置所有引用之前使窗口可见。您可以稍微修改代码,以便在使窗口可见之前正确初始化所有引用,而不是尝试延迟“修复”此问题(处理症状而不是根本问题)

下面是一个更新的窗口构造函数:

public Window(JPanel panel)
{
    super("Knight Quest");
    // DELETED loading screen
    setLayout(new BorderLayout());
    add(panel, BorderLayout.CENTER);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(600,550);
    setLocation(525, 225);
    // DELETED setVisible(true);
}
以及另一个类中更新的窗口字段初始值设定项:

private Window window = new Window(main());
// Added initializer to make the Window, then set it as visible
// You could also move this initializer code into the constructor
{ window.setVisible(true); }
现在我认为应该完全构建窗口,在窗口可见之前,应该设置所有引用(包括
Window
)。这样用户就没有机会过早点击


如果确实存在窗口太长时间不可见的问题,那么您可能希望执行@TedHopp的回答中建议的操作,而不是添加延迟,您可以直接使用它,以便窗口在准备好后立即更新,而不是总是等待2.5秒。在UI事件队列中的当前事件之后进行调度这一事实应该足够了,没有任何特定的延迟。

您需要延迟以避免出现
NullPointerException
这一事实意味着您的代码中存在排序错误。看起来您只是在设置所有引用之前使窗口可见。您可以稍微修改代码,以便在使窗口可见之前正确初始化所有引用,而不是尝试延迟“修复”此问题(处理症状而不是根本问题)

下面是一个更新的窗口构造函数:

public Window(JPanel panel)
{
    super("Knight Quest");
    // DELETED loading screen
    setLayout(new BorderLayout());
    add(panel, BorderLayout.CENTER);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(600,550);
    setLocation(525, 225);
    // DELETED setVisible(true);
}
以及另一个类中更新的窗口字段初始值设定项:

private Window window = new Window(main());
// Added initializer to make the Window, then set it as visible
// You could also move this initializer code into the constructor
{ window.setVisible(true); }
现在我相信窗口应该被完全构建,所有的参考