首页 > 解决方案 > Java Swing 偶尔会给出 NullPointerExceptions,但没有指明它在我的代码中发生的位置

问题描述

我正在为一项任务制作一个聊天客户端,并且我已经设法让一切工作得很好。但是,我有一个错误,根本找不到原因。将消息打印到我的一个聊天窗口时,我收到 NullPointerException。问题是,代码仍然完全按照它应该做的并且非常不一致。我可以打印 5 条消息并得到 5 次,或者打印 20 条却没有得到。

到目前为止,我已经能够将错误缩小到一个函数,但无法将其缩小到函数中的一行。我收到的错误消息也没有多大帮助。我已经尝试注释掉每一行代码,但仍然无法找出问题所在。我什至尝试使用 try and catch 来捕获错误,但它没有用。

以下是导致错误所需的最少代码。

import java.awt.*;
import java.util.*;

// Import window library and listeners
import javax.swing.*;
import java.awt.event.*;

// Import time libraries
import java.util.Date;
import java.text.SimpleDateFormat;

public class ChatClientTest {
    // Initialize user information
    private String nickname = "testNickname";

    // Track open windows
    private ArrayList<JFrame> windows = new ArrayList<>();

    public ChatClientTest() {
        openWindow("@ChatBot");
        openWindow("@someUser");

        // Create thread to listen to server
        Thread server = new Thread(new Runnable() {
            @Override
            public void run() {
                // Run listenToServer in separate thread
                listenToServer();
            }
        });
        // Start server listening thread
        server.start();
    }

    private void listenToServer() {
        int i = 0;
        while (true) {
            for (JFrame window : windows) {
                try {
                    Thread.sleep(2000);
                    printToWindow(window.getTitle(), nickname, "Test message" + i);
                } catch (InterruptedException e) {
                    System.out.println("Interrupted");
                }
            }
            i++;
        }
    }

    // Opens a new chat window for a given channel or user
    private void openWindow(String name) {

        // Create new JFrame with a text area and scroll bar
        JFrame frame = new JFrame(name);
        JTextArea textArea = new JTextArea(20,60);
        JScrollPane scrollBar = new JScrollPane(textArea);
        JTextArea inputArea = new JTextArea("");

        // Set text area properties
        textArea.setMargin(new Insets(5,10,20,10));
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setEditable(false);

        // Set scroll bar properties
        scrollBar.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        // Set input field properties
        inputArea.setMargin(new Insets(5,10,5,10));
        inputArea.setLineWrap(true);
        inputArea.setWrapStyleWord(true);

        // Add event listener on input area to track enter being pressed
        inputArea.addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode() == KeyEvent.VK_ENTER){
                    // Stop new line
                    e.consume();

                    // Check message isn't empty
                    if (!inputArea.getText().equals("")) {
                        // Print to the window and clear the text area
                        printToWindow(nickname, name, inputArea.getText());
                        inputArea.setText("");
                    }
                }
            }
            // These are required but don't do anything
            @Override public void keyReleased(KeyEvent e) {}
            @Override public void keyTyped(KeyEvent e) {}
        });

        // put things into the frame
        frame.add(scrollBar, BorderLayout.CENTER);
        frame.add(inputArea, BorderLayout.SOUTH);
        frame.pack();

        // Set properties of the frame
        frame.setSize(400,500);
        frame.setVisible(true);

        // Print a different starting message depending on the recipient
        if (name.startsWith("#")) { // Joining a channel
            textArea.append("Welcome, " + nickname + ", to the " + name + " channel! Be nice, start chatting and get to know some people. Leave the channel to close this window.");
        } else { // Messaging a user
            textArea.append("This is the start of your messages with " + name + ". Be nice and have fun chatting.");
        }
        windows.add(frame);
    }

    // Prints messages to/from a given channel in the appropriate chat window
    private void printToWindow(String sender, String recipient, String message) {

        // Iterate through windows
        for (JFrame window : windows) {

            // Get current timestamp
            String timestamp = new SimpleDateFormat("h:mm a").format(new Date()).toLowerCase();

            // Check who the recipient/sender is so the appropriate window is chosen
            if (recipient.equals(nickname) && window.getTitle().equalsIgnoreCase(sender)) { // User is the recipient

                // Get the JFrames textArea and scrollPane
                JScrollPane scrollPane = (JScrollPane) window.getContentPane().getComponent(0);
                JTextArea textArea = (JTextArea) scrollPane.getViewport().getView();

                // Make the textArea editable
                textArea.setEditable(true);

                // Append the message to the window and scroll window down
                textArea.append("\n\n" + sender.replace("@", "") + " | " + timestamp + "\n" + message);
                textArea.validate();
                scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());
                scrollPane.validate();

                // Make it non-editable again
                textArea.setEditable(false);

            } else if (window.getTitle().equalsIgnoreCase(recipient)) { // Any other recipient

                // Get the JFrames textArea and scrollPane
                JScrollPane scrollPane = (JScrollPane) window.getContentPane().getComponent(0);
                JTextArea textArea = (JTextArea) scrollPane.getViewport().getView();

                // Make the textArea editable
                textArea.setEditable(true);

                // Append the message to the window
                textArea.append("\n\n" + sender.replace("@", "") + " | " + timestamp + "\n" + message);
                textArea.validate();
                scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum());
                scrollPane.validate();

                // Make it non-editable again
                textArea.setEditable(false);
            }
        }
    }

    public static void main(String[] args) {
        new ChatClientTest();
    }
}

这是intellij给我的错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.text.WrappedPlainView$WrappedLine.paint(WrappedPlainView.java:584)
at javax.swing.text.BoxView.paintChild(BoxView.java:161)
at javax.swing.text.BoxView.paint(BoxView.java:433)
at javax.swing.text.WrappedPlainView.paint(WrappedPlainView.java:369)
at javax.swing.plaf.basic.BasicTextUI$RootView.paint(BasicTextUI.java:1434)
at javax.swing.plaf.basic.BasicTextUI.paintSafely(BasicTextUI.java:737)
at javax.swing.plaf.basic.BasicTextUI.paint(BasicTextUI.java:881)
at javax.swing.plaf.basic.BasicTextUI.update(BasicTextUI.java:860)
at javax.swing.JComponent.paintComponent(JComponent.java:780)
at javax.swing.JComponent.paint(JComponent.java:1056)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JViewport.paint(JViewport.java:728)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
at javax.swing.JComponent._paintImmediately(JComponent.java:5158)
at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
at javax.swing.RepaintManager$4.run(RepaintManager.java:831)
at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

该程序仍然完全按预期运行,它只是随机给出此错误。

有人可以帮我找到 NullPointerException 的原因吗?如果对该程序的工作方式有任何不清楚的地方,请告诉我,并感谢您的帮助。这是我在这里的第一篇文章,所以我希望我把一切都说清楚了。

标签: javamultithreadingswingnullpointerexceptionirc

解决方案


推荐阅读