我正在聊天客户端/服务器上工作。在客户端中,我有一个名为ClientGui
的类,以及一个名为InputPane
的子类,它扩展了JPanel
。 ClientGui
处理与GUI相关的客户端事务的主要部分,但InputPane
仅处理来自用户的输入。
在尝试在NullPointerException
类的InputPane
对象中设置字体时,我不断变得奇怪ClientGui
。以下是我的一些代码:
public ClientGui() {
// configure JFrame
this.serverOutput = new JTextPane();
this.input = new InputPane();
// configure JScrollPane
// configure other objects
// various set up methods
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(input, BorderLayout.PAGE_END);
}
如您所见,input
对象正在初始化。这是它的构造函数:
public InputPane() {
this.inputField = new JTextField();
this.send = new JButton("Send");
// set size
this.setFont(getFont());
// various methods
// add components
}
当我尝试设置字体时,它会抛出NullPointerException
。通过各种println()
调用,我发现inputField
和send
为空。我尝试在构造函数中放置println()
方法,但没有调用(和/或打印)。
我很困惑。如果有人能给出解释,那将会有很大帮助。谢谢。
编辑:这是StackTrace:
Exception in thread "main" java.lang.NullPointerException
at net.dean.tcp.client.gui.ClientGui$InputPane.setFont(ClientGui.java:518)
at javax.swing.LookAndFeel.installColorsAndFont(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installDefaults(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installUI(Unknown Source)
at javax.swing.JComponent.setUI(Unknown Source)
at javax.swing.JPanel.setUI(Unknown Source)
at javax.swing.JPanel.updateUI(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at net.dean.tcp.client.gui.ClientGui$InputPane.<init>(ClientGui.java:496)
at net.dean.tcp.client.gui.ClientGui.<init>(ClientGui.java:138)
at net.dean.tcp.client.gui.ClientGui.main(ClientGui.java:44)
编辑2 :以下是ClientGui$InputPane.setFont(Font)
方法:
public void setFont(Font f) {
super.setFont(f);
inputField.setFont(f);
send.setFont(f);
Dimension size = getSizeFromFont();
// Dimension based on getFont()'s height
send.setPreferredSize(size);
inputField.setPreferredSize(size);
}
答案 0 :(得分:4)
问题是Swing框架将setFont
作为JPanel
构造函数的一部分进行调用。由于这在构造函数的主体之前执行,因此在InputPane.setFont
和send
成员变量初始化之前调用inputField
。我认为,这里唯一干净的解决方案是在InputPane.setFont
:
public void setFont(Font f) {
super.setFont(f);
if (inputField != null) {
inputField.setFont(f);
}
if (send != null) {
send.setFont(f);
}
Dimension size = getSizeFromFont();
// Dimension based on getFont()'s height
if (send != null) {
send.setPreferredSize(size);
}
if (inputField != null) {
inputField.setPreferredSize(size);
}
}
(您可以重新组织调用以减少空值检查。)
顺便说一句,这是为什么it is bad practice to call an overridable method from a constructor的一个很好的例子。但Swing就是这样,并且抱怨它没有任何利润,所以我会停在这里。 :)
答案 1 :(得分:0)
使用setFont
设置字体时,您将从getFont
方法获取字体并进行设置。这个getFont()
更有可能返回NULL,这可能是原因。另外在我看来inputField
和send
对象在inputPane
对象中都不能为NULL,除非你明确地将它们设为NULL。