提问人:JavaFreak0xFFFF 提问时间:8/28/2021 更新时间:8/28/2021 访问量:300
Java swing 应用程序在线程“AWT-EventQueue-0”中抛出 NullPointerException,原因不明
Java swing application throws NullPointerException in thread "AWT-EventQueue-0" for unkown reason
问:
我使用 swing 包在 Java 中创建了一个控制台应用程序,但它有问题。首先,应用程序的工作原理:
应用程序在屏幕上打开一个 JFrame(Console 类),其中包含一个 JPanel(ConsoleScreen 类)。JPanel 只包含一个不可编辑、可滚动的 JTextArea。控制台有 3 种不同的方法,可以通过编程方式调用: 1:打印(将文本打印到控制台) 2:输入(从控制台获取内联输入并返回) 3:清空(清空控制台)
有关输入法的详细信息:
调用输入法时,它使文本区域暂时可编辑,并允许用户输入内联输入。但是,它会禁止它们设置文本区域上其余文本的格式(通过使用 TextAreaDocumentFilter 类的实例)。在等待输入时,程序在主线程上重复调用 sleep(long millis) 方法,以尽可能少地浪费 CPU 时间。此外,文本区域有一个 DocumentListener,一旦用户单击 Enter,为了移动到下一行,在主线程上调用 interrupt() 方法,使程序停止等待输入,并且文本区域再次变得不可编辑。然后,返回用户给出的内联输入。
问题:
问题与输入法有关。基本上,每当我调用该方法并从控制台获取输入时,一切似乎都运行良好(正确的结果显示在控制台上并返回正确的输入)。但是,与此同时,几乎每次程序从控制台获取输入时,线程“AWT-EventQueue-0”中都会抛出 NullPointerException,我不明白为什么。我尝试将程序的许多不同部分包含在 try/catch 语句中,但仍然抛出异常,好像什么都没有改变。此外,我尝试在程序中几乎到处添加打印语句,拼命地试图找到错误的根源,但毫无用处。
你能帮我解决这个问题吗,或者至少告诉我为什么会这样?这是控制台的代码、一个测试程序以及我得到的最常见的堆栈跟踪之一。尝试运行测试程序,并自己查看错误。感谢您的关注!
控制台类:
package interpreter;
import javax.swing.JFrame;
final class Console extends JFrame{
private ConsoleScreen screen;
Console(){
setTitle("Console");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setUndecorated(false);
screen = new ConsoleScreen();
add(screen);
setVisible(true);
}
void print(String text) {
screen.print(text);
}
String input() {
return screen.input();
}
void empty() {
screen.empty();
}
}
ConsoleScreen 类:
package interpreter;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;
final class ConsoleScreen extends JPanel{
Thread mainThread;
private JTextArea textArea;
private DocumentListener textAreaDocumentListener;
private TextAreaDocumentFilter textAreaDocumentFilter;
private boolean takingInput;
private int inputStartIndex = 0; /*text index after which input is taken */
ConsoleScreen(){
mainThread = Thread.currentThread();
textAreaDocumentFilter = new TextAreaDocumentFilter();
textAreaDocumentListener = new TextAreaDocumentListener();
setLayout(new GridLayout(1, 1));
fillScreen();
}
void fillScreen() {
textArea = new JTextArea("");
textArea.setBackground(Color.BLACK);
textArea.setForeground(Color.WHITE);
textArea.setCaretColor(Color.WHITE);
textArea.setFont(new Font("Consolas", Font.PLAIN, 25));
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
textArea.setEditable(false);
textArea.getDocument().addDocumentListener(textAreaDocumentListener);
((AbstractDocument)textArea.getDocument()).setDocumentFilter(textAreaDocumentFilter);
JScrollPane textAreaScroller = new JScrollPane(textArea);
textAreaScroller.setBorder(null);
add(textAreaScroller);
}
//prints text to the console
void print(String text) {
textArea.append(text);
textArea.setCaretPosition(textArea.getText().length());
inputStartIndex += text.length();
}
//takes one line of input from the console
String input() {
takingInput = true;
textArea.setEditable(true);
while(takingInput) {
try {
Thread.sleep(999999999);
}catch(InterruptedException e) {break;}
}
textArea.setEditable(false);
String inputText = textArea.getText().substring(inputStartIndex, textArea.getText().length() - 1);
inputStartIndex = textArea.getText().length();
return inputText;
}
//empties the console
void empty() {
textArea.setText("");
inputStartIndex = 0;
}
/* does not allow the user to format the text behind the inputStartIndex */
private class TextAreaDocumentFilter extends DocumentFilter {
public void insertString(final FilterBypass fb, final int offset, final String string, final AttributeSet attr)
throws BadLocationException {
if (!takingInput || offset >= inputStartIndex)
super.insertString(fb, offset, string, attr);
}
public void remove(final FilterBypass fb, final int offset, final int length) throws BadLocationException {
if (!takingInput || offset >= inputStartIndex)
super.remove(fb, offset, length);
}
public void replace(final FilterBypass fb, final int offset, final int length, final String text, final AttributeSet attrs)
throws BadLocationException {
if (!takingInput || offset >= inputStartIndex)
super.replace(fb, offset, length, text, attrs);
}
}
/* makes the program stop receiving input once the user has moved to the next line of the console */
private class TextAreaDocumentListener implements DocumentListener {
@Override
public void insertUpdate(DocumentEvent e) {
if(takingInput) {
String text = textArea.getText();
if(text.length() > inputStartIndex && text.charAt(text.length() - 1) == '\n') {
mainThread.interrupt();
takingInput = false;
}
}
}
@Override
public void removeUpdate(DocumentEvent e) {}
@Override
public void changedUpdate(DocumentEvent e) {
insertUpdate(e);
}
};
}
测试类:
package interpreter;
class Test {
public static void main(String[] args) {
Console console = new Console();
String input = "";
do {
console.print("Enter a string: ");
input = console.input();
console.print("String entered: " + input + "\n\n");
}while(!input.equals("END"));
}
}
我得到的一个常见的堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "javax.swing.text.JTextComponent.getHighlighter()" because "host" is null
at java.desktop/javax.swing.text.WrappedPlainView$WrappedLine.paint(WrappedPlainView.java:716)
at java.desktop/javax.swing.text.BoxView.paintChild(BoxView.java:162)
at java.desktop/javax.swing.text.BoxView.paint(BoxView.java:434)
at java.desktop/javax.swing.text.WrappedPlainView.paint(WrappedPlainView.java:501)
at java.desktop/javax.swing.plaf.basic.BasicTextUI$RootView.paint(BasicTextUI.java:1530)
at java.desktop/javax.swing.plaf.basic.BasicTextUI.paintSafely(BasicTextUI.java:759)
at java.desktop/javax.swing.plaf.basic.BasicTextUI.paint(BasicTextUI.java:917)
at java.desktop/javax.swing.plaf.basic.BasicTextUI.update(BasicTextUI.java:896)
at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:797)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedImpl(RepaintManager.java:1643)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1618)
at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556)
at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
答: 暂无答案
评论
Event Dispatch Thread (EDT)
SwingWorker
Tasks that have interim results
takingInput
volatile
@