[英]JavaFX how to set the text of a label in the calling controller, from the called controller
[英]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.