我在17java使用JavaFX(使用fxml)和java套接字编写消息传递应用程序。我设法与服务器建立了通信,在我的Client.java我想发送gui文本区域中的任何内容(写入消息)。这个gui由AppController类控制。当我调用appController. getMessageArea().getText()时,我得到一个空指针异常(错误日志如下)
我的CLient.java
public class Client {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private String username;
private AppController appController;
public Client(Socket socket, String username) throws IOException {
this.appController = new AppController();
try {
this.socket = socket;
this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.out = new PrintWriter(socket.getOutputStream(), true);
this.username = username;
out.println(username);
} catch (IOException e) {
closeAll();
}
}
public void send() {
String message;
try {
while(socket.isConnected()){
message = appController.getMessageArea().getText();
out.println(message);
}
} catch (Exception e) {
e.printStackTrace();
//closeAll(socket, in, out);
}
}
public void closeAll(Closeable... objects){
for(Closeable c : objects){
try {
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void listen(){
new Thread(() -> {
String receivedMessage;
while(socket.isConnected()){
try{
receivedMessage = in.readLine();
Label received = new Label(receivedMessage);
appController.getMessageContainer().getChildren().add(received);
appController.getScrollPane().setVvalue(1.0);
}catch(Exception e){
closeAll(socket, in, out);
}
}
}).start();
}
public Socket getSocket() {
return socket;
}
public String getUsername() {
return username;
}
}
这里是AppController.java
public class AppController implements Initializable {
@FXML
private TextArea messageArea;
@FXML
private VBox messageContainer;
@FXML
private ScrollPane scrollPane;
@FXML
private Label nameTag;
@FXML
private Button sendButton;
private Client client;
@Override
public void initialize(URL url, ResourceBundle resources){
try{
System.out.println(getMessageArea());
messageArea.clear();
sendButton.disableProperty().bind(messageArea.textProperty().isEmpty());
nameTag.setText(LoginController.user.getName());
client = new Client(new Socket("localhost", 1234), LoginController.user.getName());
}catch (Exception e){
e.printStackTrace();
}
}
public void send(){
//String message = messageArea.getText();
Label sent = new Label(client.getUsername() + "> " + messageArea.getText());
messageContainer.getChildren().add(sent);
scrollPane. setVvalue(1.0);
client.send();
messageArea.clear();
}
public VBox getMessageContainer() {
return messageContainer;
}
public ScrollPane getScrollPane() {
return scrollPane;
}
public TextArea getMessageArea() {
return messageArea;
}
}
这是错误日志
java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TextArea.getText()" because the return value of "messageapp.AppController.getMessageArea()" is null
at messageapp/messageapp.util.Client.send(Client.java:35)
at messageapp/messageapp.AppController.send(AppController.java:47)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1854)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1724)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8792)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:203)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:208)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1878)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:557)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:943)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:833)
Process finished with exit code 0
如果你还需要什么告诉我谢谢
注释为@FXML
的字段在控制器中初始化,控制器(通常)是由.FXMLLoader
创建的对象,每次加载相应的FXML文件时。它们不会神奇地在同一类的任意对象中初始化(即使它们是,它们会被初始化为什么?)。
如果您想在Client
类中引用控制器,则需要为其提供对FXMLLoader
创建的实际控制器实例的引用。
不管怎样,这里的设计是丑陋的。你的Client
类不知道控制器有一个TextArea
,也不应该访问它。这显然违反了关注点分离,并且使得在不改变应用程序代码的任意其他部分的情况下更改UI设计(使用不同的控件)变得困难。
相反,定义您的Client. send()
方法以获取表示要发送的消息的参数,然后从控制器中相应地调用它。这避免了空指针异常并修复了丑陋的设计。
public class Client {
// ...
public void send(String message) {
// this implementation looks wrong. Why are you repeatedly sending the message?
try {
while(socket.isConnected()){
out.println(message);
}
} catch (Exception e) {
e.printStackTrace();
//closeAll(socket, in, out);
}
}
}
然后
public class AppController implements Initializable {
@FXML
private TextArea messageArea;
@FXML
private VBox messageContainer;
// ...
public void send(){
String message = messageArea.getText();
Label sent = new Label(client.getUsername() + "> " + message);
messageContainer.getChildren().add(sent);
scrollPane. setVvalue(1.0);
client.send(message);
messageArea.clear();
}
}