簡體   English   中英

JavaFx從另一個控制器設置標簽文本

[英]JavaFx set Label text from another controller

我想將標簽的文本更改為不是來自我將控制器聲明為 fxml 文件的類。

我想在 Main 文件的 ClientAccept 類中更改它,但是當我嘗試從 ClientAccept 獲取 Controller 類並在 Controller 類中運行函數時,我得到 NullPointerException '因為“this.sStatus”為空'。 我無法解決它。

主.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("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());
            }
        }
    }
}

}

控制器.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);
}

}

示例.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。

@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);
    }

    // Similarly for other data shared by the app....

}

然后

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());
    }


}

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());
            }
        }
    }
}

然后把它們綁在一起:

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();

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM