JavaFx从另一个控制器设置Label文本

huangapple go评论75阅读模式
英文:

JavaFx set Label text from another controller

问题

我想要在声明控制器的类中更改标签的文本而不是从类中更改文本

我想要在主文件的ClientAccept类中进行更改但是当我尝试从ClientAccept获取控制器类并从控制器类运行函数时我会得到NullPointerException因为"this.sStatus"为空我无法解决这个问题

Main.java:

package sample;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

public class Main extends Application {

    ServerSocket ss;
    HashMap clientColl = new HashMap();

    @Override
    public void start(Stage stage) throws Exception{

        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        Controller controller = new Controller();
        loader.setController(controller);
        Parent parent = loader.load();
        Scene scene  = new Scene(parent);
        stage.setScene(scene);
        stage.show();

        try{
            ss = new ServerSocket(8989);
        }catch (IOException ioe){
            System.out.println(ioe.getMessage());
        }

        ClientAccept cla = new ClientAccept();
        cla.isWorking();

    }

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

    class ClientAccept extends Thread{

        public void isWorking() throws IOException {
            Controller controller = new Controller();
            controller.setsStatus("test");
        }

        public void run(){
            while(true){
                try {
                    Socket s = ss.accept();
                    String i = new DataInputStream(s.getInputStream()).readUTF();
                    if(clientColl.containsKey(i)){
                        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
                        dos.writeUTF("Już jesteś Zarejestrowany");
                    }else {
                        clientColl.put(i, s);
                        Platform.runLater(() -> {
                            controller.setsStatus("TextToLabel");
                        });
                    }
                }catch (Exception e){
                    System.out.println(e.getMessage());
                }
            }
        }
    }
}

Controller.java:

package sample;

import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;

public class Controller {
    @FXML
    Label sStatus;
    @FXML
    TextArea msgBox;

    void setsStatus(String text){
        sStatus.setText(text);
        System.out.println(text);
    }
}

sample.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <TextArea fx:id="msgBox" layoutX="53.0" layoutY="67.0" prefHeight="278.0" prefWidth="512.0" />
      <Label layoutX="67.0" layoutY="28.0" text="Server Status: " />
      <Label fx:id="sStatus" layoutX="142.0" layoutY="28.0" text=".............." />
   </children>
</AnchorPane>

我只是得到了NullPointerException
英文:

I want to change text for label not from class where i declare controller to fxml file.

I want to change it in ClientAccept class in Main file, but when i tried get Controller class and run function in Controller class from ClientAccept i get NullPointerException 'because "this.sStatus" is null'. I cant resolve it.

Main.java:

package sample;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.stage.Stage;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class Main extends Application {
ServerSocket ss;
HashMap clientColl = new HashMap();
@Override
public void start(Stage stage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource(&quot;sample.fxml&quot;));
Controller controller = new Controller();
loader.setController(controller);
Parent parent = loader.load();
Scene scene  = new Scene(parent);
stage.setScene(scene);
stage.show();
try{
ss = new ServerSocket(8989);
}catch (IOException ioe){
System.out.println(ioe.getMessage());
}
ClientAccept cla = new ClientAccept();
cla.isWorking();
}
public static void main(String[] args) {
launch(args);
}
class ClientAccept extends Thread{
public void isWorking() throws IOException {
Controller controller = new Controller();
controller.setsStatus(&quot;test&quot;);
}
public void run(){
while(true){
try {
Socket s = ss.accept();
String i = new DataInputStream(s.getInputStream()).readUTF();
if(clientColl.containsKey(i)){
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(&quot;Już jesteś Zarejestrowany&quot;);
}else {
clientColl.put(i, s);
Platform.runLater(()-&gt;{
controller.setsStatus(&quot;TextToLabel&quot;);
});
}
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
}
}

Controller.java:

package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
public class Controller {
@FXML
Label sStatus;
@FXML
TextArea msgBox;
void setsStatus(String text){
sStatus.setText(text);
System.out.println(text);
}
}

sample.fxml:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;?import javafx.scene.control.Label?&gt;
&lt;?import javafx.scene.control.TextArea?&gt;
&lt;?import javafx.scene.layout.AnchorPane?&gt;
&lt;AnchorPane maxHeight=&quot;-Infinity&quot; maxWidth=&quot;-Infinity&quot; minHeight=&quot;-Infinity&quot; minWidth=&quot;-Infinity&quot;     prefHeight=&quot;400.0&quot; prefWidth=&quot;600.0&quot; xmlns=&quot;http://javafx.com/javafx/11.0.1&quot; xmlns:fx=&quot;http://javafx.com/fxml/1&quot;&gt;
&lt;children&gt;
&lt;TextArea fx:id=&quot;msgBox&quot; layoutX=&quot;53.0&quot; layoutY=&quot;67.0&quot; prefHeight=&quot;278.0&quot; prefWidth=&quot;512.0&quot; /&gt;
&lt;Label layoutX=&quot;67.0&quot; layoutY=&quot;28.0&quot; text=&quot;Server Status: &quot; /&gt;
&lt;Label fx:id=&quot;sStatus&quot; layoutX=&quot;142.0&quot; layoutY=&quot;28.0&quot; text=&quot;..............&quot; /&gt;
&lt;/children&gt;
&lt;/AnchorPane&gt;

I just get NullPointerException.

答案1

得分: 2

@FXML 注解的字段只会在 FXMLLoader 使用的 Controller 实例中初始化。它们不会在其他实例中初始化,比如你在 ClientAccept 类中创建的实例。

一个简单粗暴的方法是让 ClientAccept 类引用正确的 Controller 实例。例如:

public void start(Stage stage) throws Exception{
    
    FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
    Controller controller = new Controller();
    loader.setController(controller);
    Parent parent = loader.load();
    Scene scene  = new Scene(parent);
    stage.setScene(scene);
    stage.show();
    
    try{
        ss = new ServerSocket(8989);
    }catch (IOException ioe){
        System.out.println(ioe.getMessage());
    }
    
    ClientAccept cla = new ClientAccept(controller);
    cla.isWorking();
    
}
    
class ClientAccept extends Thread{
    
    private final Controller controller ;
    
    public ClientAccept(Controller controller) {
        this.controller = controller ;
    }
    
    public void isWorking() throws IOException {
        controller.setsStatus("test");
    }
    
    public void run(){
        while(true){
            try {
                Socket s = ss.accept();
                String i = new DataInputStream(s.getInputStream()).readUTF();
                if(clientColl.containsKey(i)){
                    DataOutputStream dos = new DataOutputStream(s.getOutputStream());
                    dos.writeUTF("Już jesteś Zarejestrowany");
                }else {
                    clientColl.put(i, s);
                    Platform.runLater(()->{
                        controller.setsStatus("TextToLabel");
                    });
                }
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
    }
}

通常不推荐像这样共享控制器实例。更好的方法是使用 MVC 设计并共享模型。例如,你可以这样做:

public class DataModel {
    
    private final StringProperty status = new SimpleStringProperty();
    
    public StringProperty statusProperty() {
        return status ;
    }
    
    public final String getStatus() {
        return statusProperty().get();
    }
    
    public final void setStatus(String status) {
        statusProperty().set(status);
    }

    // 同样地,对于应用程序共享的其他数据也可以这样做...

}

然后

```java
public class Controller {
    @FXML
    Label sStatus;
    @FXML
    TextArea msgBox;
    
    private final DataModel model ;
    
    public Controller(DataModel model) {
        this.model = model ;
    }
    
    @FXML
    public void initialize() {
        sStatus.textProperty().bind(model.statusProperty());
    }
    
    
}


```java
class ClientAccept extends Thread{
    
    private final DataModel model ;
    
    public ClientAccept(DataModel model) {
        this.model = model ;
    }
    
    public void isWorking() throws IOException {
        model.setStatus("test");
    }
    
    public void run(){
        while(true){
            try {
                Socket s = ss.accept();
                String i = new DataInputStream(s.getInputStream()).readUTF();
                if(clientColl.containsKey(i)){
                    DataOutputStream dos = new DataOutputStream(s.getOutputStream());
                    dos.writeUTF("Już jesteś Zarejestrowany");
                }else {
                    clientColl.put(i, s);
                    Platform.runLater(()->{
                        model.setStatus("TextToLabel");
                    });
                }
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
    }
}

然后将它们统统联系在一起

```java
public void start(Stage stage) throws Exception{

    DataModel model = new DataModel();
    
    FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
    Controller controller = new Controller(model);
    loader.setController(controller);
    Parent parent = loader.load();
    Scene scene  = new Scene(parent);
    stage.setScene(scene);
    stage.show();
    
    try{
        ss = new ServerSocket(8989);
    }catch (IOException ioe){
        System.out.println(ioe.getMessage());
    }
    
    ClientAccept cla = new ClientAccept(model);
    cla.isWorking();
    
}
英文:

The @FXML-annotated fields are only initialized in the Controller instance used by the FXMLLoader. They won't be initialized in other instances, such as the one you create in your ClientAccept class.

A quick-and-dirty approach is just to arrange for the ClientAccept to have a reference to the correct Controller instance. E.g.

public void start(Stage stage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource(&quot;sample.fxml&quot;));
Controller controller = new Controller();
loader.setController(controller);
Parent parent = loader.load();
Scene scene  = new Scene(parent);
stage.setScene(scene);
stage.show();
try{
ss = new ServerSocket(8989);
}catch (IOException ioe){
System.out.println(ioe.getMessage());
}
ClientAccept cla = new ClientAccept(controller);
cla.isWorking();
}
class ClientAccept extends Thread{
private final Controller controller ;
public ClientAccept(Controller controller) {
this.controller = controller ;
}
public void isWorking() throws IOException {
controller.setsStatus(&quot;test&quot;);
}
public void run(){
while(true){
try {
Socket s = ss.accept();
String i = new DataInputStream(s.getInputStream()).readUTF();
if(clientColl.containsKey(i)){
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(&quot;Już jesteś Zarejestrowany&quot;);
}else {
clientColl.put(i, s);
Platform.runLater(()-&gt;{
controller.setsStatus(&quot;TextToLabel&quot;);
});
}
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
}

It's generally not very good practice to share controller instances around like this. A better approach is to use a MVC design and share the model. E.g. you could do

public class DataModel {
private final StringProperty status = new SimpleStringProperty();
public StringProperty statusProperty() {
return status ;
}
public final String getStatus() {
return statusProperty().get();
}
public final void setStatus(String status) {
statusProperty().set(status);
}
// Similarly for other data shared by the app....
}

Then

public class Controller {
@FXML
Label sStatus;
@FXML
TextArea msgBox;
private final DataModel model ;
public Controller(DataModel model) {
this.model = model ;
}
@FXML
public void initialize() {
sStatus.textProperty().bind(model.statusProperty());
}
}

and

class ClientAccept extends Thread{
private final DataModel model ;
public ClientAccept(DataModel model) {
this.model = model ;
}
public void isWorking() throws IOException {
model.setStatus(&quot;test&quot;);
}
public void run(){
while(true){
try {
Socket s = ss.accept();
String i = new DataInputStream(s.getInputStream()).readUTF();
if(clientColl.containsKey(i)){
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(&quot;Już jesteś Zarejestrowany&quot;);
}else {
clientColl.put(i, s);
Platform.runLater(()-&gt;{
model.setStatus(&quot;TextToLabel&quot;);
});
}
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
}

and then just tie it all together:

public void start(Stage stage) throws Exception{
DataModel model = new DataModel();
FXMLLoader loader = new FXMLLoader(getClass().getResource(&quot;sample.fxml&quot;));
Controller controller = new Controller(model);
loader.setController(controller);
Parent parent = loader.load();
Scene scene  = new Scene(parent);
stage.setScene(scene);
stage.show();
try{
ss = new ServerSocket(8989);
}catch (IOException ioe){
System.out.println(ioe.getMessage());
}
ClientAccept cla = new ClientAccept(model);
cla.isWorking();
}

huangapple
  • 本文由 发表于 2020年10月6日 02:38:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/64214355.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定