我正在为任务分配聊天客户端,并且我设法使所有工作正常进行。但是,我有一个错误,根本找不到原因。将消息打印到我的一个聊天窗口中时,出现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的原因吗?让我知道该程序如何工作尚不清楚,谢谢您的帮助。这是我在这里的第一篇文章,所以我希望我把所有事情都弄清楚。