java - ObjectOutputStream 在 PlayerList.java 中不可用 - 无法获取表的数据

标签 java multithreading networking javafx-8 scenebuilder

好的,再来一次。这是一个带有相关代码的新项目。正如您在文本字段中看到的,即使 initData 应该初始化 testVar 变量,但它并没有发生,并且在initialize() 中变量为 null。不过,我需要在那里获取变量,这样我就可以将网络连接中的数据获取到表中。代码如下:

FXMLController.java:

package de.freakyonline.testproject;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;

public class FXMLController implements Initializable {
    String testVar;

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    private TextArea testTextArea;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    // Here it's null    
        testTextArea.appendText("TestVar: " + testVar);

    }

    void initData(Remote remoteObj) {
        this.testVar = remoteObj.getVar();
    }    
}

MainApp.java:

package de.freakyonline.testproject;

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


public class MainApp extends Application {
    Thread remote;
    Remote remoteObj;

    String testVar = new String("success");

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

        FXMLLoader root = new FXMLLoader(
            getClass().getResource("/fxml/Scene.fxml")
        );

        try {
            remoteObj = new Remote(testVar);
            remote = new Thread(remoteObj);
        } catch (Exception ex) { ex.printStackTrace(); }
        remote.start();

        Scene scene = new Scene((Parent) root.load());
        FXMLController controller = root.<FXMLController>getController(); 
        controller.initData(remoteObj);

        scene.getStylesheets().add("/styles/Styles.css");

        stage.setTitle("TestProjects ...");
        stage.setScene(scene);
        stage.show();


    }

    /**
     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

场景.fxml:

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

<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.freakyonline.testproject.FXMLController">
   <center>
      <TextArea fx:id="testTextArea" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
   </center>
</BorderPane>

远程.java:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package de.freakyonline.testproject;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

/**
 *
 * @author uwe
 */
public class Remote implements Runnable {
    private String testVar;

    public Remote (String testVar) {
        this.testVar = testVar;
    }

    public String getVar() {
        return testVar;
    }

    public void run() {
    }
}

最佳答案

加载 FXML 时, Controller 的 initialize() 方法由 FXMLLoader 调用,即在调用 load() 期间调用该方法。在示例代码中,您在调用 load() 之后调用 initData(),因此显然在执行 initialize() 方法时,testVar 无法初始化。由于示例代码中的 Controller 是由 FXMLLoader 创建的,因此您无法在调用 initialize() 之前调用 initData(...)

(旁白:使用一些简单的调试技术,例如使用逐步调试器,甚至在调用每个方法时打印一条消息,都可以非常清楚地说明问题所在。)

最简单的修复方法是将依赖于 testVar 的代码移至 initData() 方法(或初始化 testVar 后调用的其他方法):

public class FXMLController implements Initializable {
    String testVar;

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    private TextArea testTextArea;

    @Override
    public void initialize(URL url, ResourceBundle rb) {

    }

    void initData(Remote remoteObj) {
        this.testVar = remoteObj.getVar();
        testTextArea.appendText("TestVar: " + testVar);
    }    
}

这里的一个小缺点是 Controller 的初始化分布在多个方法中,在 Controller 生命周期的不同点执行。其他选项包括在代码中设置 Controller ,而不是在 FXML 文件中指定 Controller 类,或使用 Controller 工厂。在代码中设置 Controller 的缺点是,如果您使用工具(例如 Scene Builder)来设计 FXML,它将不知道正在使用的 Controller 类。使用 Controller 工厂更加复杂,但可以避免这个问题。

关于java - ObjectOutputStream 在 PlayerList.java 中不可用 - 无法获取表的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42615229/

相关文章:

java - 如何在 JSON 文件中循环 JSON 数据并解析而不使用数组

networking - 吞吐量和带宽差异?

networking - 在 haproxy 后端使用域而不是 IP

java - Android fragment 实现问题

java - JAVA中的枚举<->字符串比较

javax.inject 不存在

java - 如何用 RXJava 替换 Thread.sleep()

java - 忙自旋以减少上下文切换延迟(java)

Android Eclipse Debug模式 - 线程

networking - 在不同的网络上安装Kubernetes + Cilium