JavaFX,为什么TableColumn为null? [英] JavaFX, why is TableColumn null?

查看:62
本文介绍了JavaFX,为什么TableColumn为null?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如您将看到的那样,当涉及Java和Javafx时,我是一个笨拙的菜鸟.我花了很多时间阅读(各种论坛帖子和Tut),并试图弄清楚自己在哪里得到了这个问题,但是现在我要发表自己的想法,以征求了解他们业务的人的反馈. /p>

在回复时,请您抽出时间来解释为什么有些东西不起作用以及一些一般性的提示吗?到目前为止,这就是我所拥有的(我的FXML和我的两个类)任何指针都很棒!

我的FXML;

<Pane id="myScene" fx:id="myScene" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
      prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
        fx:controller="sample.TestController">
   <children>
      <TableView id="employeesTable" fx:id="employeesTable" layoutX="131.0" layoutY="64.0" prefHeight="200.0" prefWidth="360.0">
        <columns>
          <TableColumn id="colFirstName" fx:id="colFirstName" prefWidth="75.0" text="First Name" />
          <TableColumn id="colLastName" fx:id="colLastName" prefWidth="75.0" text="Last Name" />
            <TableColumn id="colEmail" fx:id="colEmail" prefWidth="75.0" text="email" />
        </columns>
      </TableView>
   </children>
</Pane>

现在我拥有Employee类;

public class Employee {

private StringProperty firstName;
private StringProperty lastName;
private StringProperty email;


public Employee(String a, String b, String c) {
    this.firstName = new SimpleStringProperty(a);
    this.lastName = new SimpleStringProperty(b);
    this.email = new SimpleStringProperty(c);
}

public Employee() {
}


public String getFirstName() {
    return firstName.get();
}

public StringProperty firstNameProperty() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName.set(firstName);
}

public String getLastName() {
    return lastName.get();
}

public StringProperty lastNameProperty() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName.set(lastName);
}

public String getEmail() {
    return email.get();
}

public StringProperty emailProperty() {
    return email;
}

public void setEmail(String email) {
    this.email.set(email);
}

}

最后,我的测试控制器的类是

public class TestController {
public Label login;
public TextField loginUserName;
public PasswordField loginPassword;
public TextField testOutput;
@FXML TableView<Employee> employeesTable;
@FXML TableColumn<Employee, String> colFirstName;
@FXML TableColumn<Employee, String> colLastName;
@FXML TableColumn<Employee, String> colEmail;
@FXML Pane myScene;

//public javafx.scene.control.TableView employeesTable;
private ObservableList<Employee> myData;
private MainController MainController;

public void loadEmployeeForm(ActionEvent actionEvent) throws IOException, SQLException, ClassNotFoundException {
    myData = FXCollections.observableArrayList(DBCON.getEmployees());
    System.out.println(myData.size());
    Parent root = FXMLLoader.load(getClass().getResource("frmEmployees.fxml"));
    Scene myScene = new Scene( root );
    sample.MainController.setScene(myScene);
    colFirstName.setCellValueFactory(new PropertyValueFactory<Employee, String>("firstName"));
    colLastName.setCellValueFactory(new PropertyValueFactory<Employee, String>("lastName"));
    colEmail.setCellValueFactory(new PropertyValueFactory<Employee, String>("email"));
    employeesTable.setItems(null);
    employeesTable.setItems(myData);
    employeesTable.setVisible(true);
}

当我将colFirstName设置为属性值工厂时,我得到了一个空指针异常,这使我认为我尚未在某处进行初始化,但是我对如何添加它一无所知.

如果我添加以下行: TableColumn colFirstName = new TableColumn("firstName");

对于我的每一个列和它的表名,它都是这样工作的(即,它不会向我抛出错误消息),但是然后我没有将任何数据加载到表视图中,因为我认为这是我在创建一个新的tableView不使用从FXML生成的视图?

我觉得这将非常简单,但是正如我所说的那样,我是一个笨拙的菜鸟,任何要点都非常有必要.

谢谢 标记

更新1;

通过myMain.fxml上的按钮调用用于加载员工表单的方法;

    <GridPane alignment="CENTER" hgap="10" prefHeight="300" prefWidth="300" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8"
          fx:controller="sample.TestController" stylesheets="/sample/myFirst.css">
    <children>
       <Button onAction="#login" text="Login" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="CENTER" />
        <Button text="GoEmployees" onAction="#loadEmployeeForm" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER" />
       <Label fx:id="login" GridPane.rowIndex="1" />
      <Label text="UserName" GridPane.columnIndex="0" GridPane.rowIndex="1" />
      <Label text="Password" GridPane.columnIndex="0" GridPane.rowIndex="2" />
      <TextField fx:id="loginUserName" GridPane.rowIndex="1" GridPane.columnIndex="1" />
      <PasswordField fx:id="loginPassword" GridPane.rowIndex="2" GridPane.columnIndex="1" blendMode="OVERLAY" />
        <TextField fx:id="testOutput" GridPane.rowIndex="4" GridPane.columnIndex="0" GridPane.columnSpan="3" />
   </children>
   <columnConstraints>
      <ColumnConstraints prefWidth="125.0" />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints prefHeight="50.0" />
   </rowConstraints>
   <padding>
      <Insets bottom="10.0" left="9.0" right="10.0" top="10.0" />
   </padding>

</GridPane>

让我的testController控制两个不同的FXML是一个问题/无法解决吗?

解决方案

FXMLLoader尝试加载fxml文件时,它将在fxml文件中创建用fx:controller定义的控制器类的新实例.然后,它创建,并将@FXML带注释的字段与fxml文件中的fx:id组件映射.最后,它调用控制器的initialize()方法.您可以在fxmlloader.load()之后使用fxmlloader.getController()获取实例化的控制器.

根据此基本工作流程,代码中的陷阱是:
myMain.fxml的控制器是TestController,但是myMain.fxml不包含带有fx:id colFirstName等的TableColumns.因此,在加载myMain.fxml时,这些字段为null.结果,尝试使用这些字段时,loadEmployeeForm()中将存在NPE.

将TableView和TableColumns移至frmEmployees.fxml的控制器,并在此控制器的initialize()方法中对其进行配置(setCellValueFactory,初始数据等).

As you will see I am a massive noob when it comes to Java and Javafx. I have spent a lot of time reading around (various forum posts, and tuts) and trying to figure out myself where I am getting this issue but it has come to the point for me to post for feedback from someone who knows their business.

When replying, please could you take the time to also explain why something isn't working and some general pointers? Here is what I have so far (my FXML and my two classes) any pointers would be fantastic!!

My FXML;

<Pane id="myScene" fx:id="myScene" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
      prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
        fx:controller="sample.TestController">
   <children>
      <TableView id="employeesTable" fx:id="employeesTable" layoutX="131.0" layoutY="64.0" prefHeight="200.0" prefWidth="360.0">
        <columns>
          <TableColumn id="colFirstName" fx:id="colFirstName" prefWidth="75.0" text="First Name" />
          <TableColumn id="colLastName" fx:id="colLastName" prefWidth="75.0" text="Last Name" />
            <TableColumn id="colEmail" fx:id="colEmail" prefWidth="75.0" text="email" />
        </columns>
      </TableView>
   </children>
</Pane>

Now the Employee class I have;

public class Employee {

private StringProperty firstName;
private StringProperty lastName;
private StringProperty email;


public Employee(String a, String b, String c) {
    this.firstName = new SimpleStringProperty(a);
    this.lastName = new SimpleStringProperty(b);
    this.email = new SimpleStringProperty(c);
}

public Employee() {
}


public String getFirstName() {
    return firstName.get();
}

public StringProperty firstNameProperty() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName.set(firstName);
}

public String getLastName() {
    return lastName.get();
}

public StringProperty lastNameProperty() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName.set(lastName);
}

public String getEmail() {
    return email.get();
}

public StringProperty emailProperty() {
    return email;
}

public void setEmail(String email) {
    this.email.set(email);
}

}

And finally the class for my test controller is

public class TestController {
public Label login;
public TextField loginUserName;
public PasswordField loginPassword;
public TextField testOutput;
@FXML TableView<Employee> employeesTable;
@FXML TableColumn<Employee, String> colFirstName;
@FXML TableColumn<Employee, String> colLastName;
@FXML TableColumn<Employee, String> colEmail;
@FXML Pane myScene;

//public javafx.scene.control.TableView employeesTable;
private ObservableList<Employee> myData;
private MainController MainController;

public void loadEmployeeForm(ActionEvent actionEvent) throws IOException, SQLException, ClassNotFoundException {
    myData = FXCollections.observableArrayList(DBCON.getEmployees());
    System.out.println(myData.size());
    Parent root = FXMLLoader.load(getClass().getResource("frmEmployees.fxml"));
    Scene myScene = new Scene( root );
    sample.MainController.setScene(myScene);
    colFirstName.setCellValueFactory(new PropertyValueFactory<Employee, String>("firstName"));
    colLastName.setCellValueFactory(new PropertyValueFactory<Employee, String>("lastName"));
    colEmail.setCellValueFactory(new PropertyValueFactory<Employee, String>("email"));
    employeesTable.setItems(null);
    employeesTable.setItems(myData);
    employeesTable.setVisible(true);
}

I get a null pointer exception when I go to set colFirstName to the property value factory which make me think I haven't initialized something somewhere but I am utterly clueless on how to go about adding that.

If I add in lines such as; TableColumn colFirstName = new TableColumn("firstName");

for each of my columns and the tablename it works (ie it doesn't throw a load of error messages at me) that way but then I don't get any data loading into the tableview because I think that's me creating a new tableView not using the one generated from the FXML?

I have a feeling it will be very simple, but as I said I am a massive noob and any points would be much obliged.

Thanks Mark

Update 1;

The method for load employee form is called from a button on myMain.fxml;

    <GridPane alignment="CENTER" hgap="10" prefHeight="300" prefWidth="300" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8"
          fx:controller="sample.TestController" stylesheets="/sample/myFirst.css">
    <children>
       <Button onAction="#login" text="Login" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="CENTER" />
        <Button text="GoEmployees" onAction="#loadEmployeeForm" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER" />
       <Label fx:id="login" GridPane.rowIndex="1" />
      <Label text="UserName" GridPane.columnIndex="0" GridPane.rowIndex="1" />
      <Label text="Password" GridPane.columnIndex="0" GridPane.rowIndex="2" />
      <TextField fx:id="loginUserName" GridPane.rowIndex="1" GridPane.columnIndex="1" />
      <PasswordField fx:id="loginPassword" GridPane.rowIndex="2" GridPane.columnIndex="1" blendMode="OVERLAY" />
        <TextField fx:id="testOutput" GridPane.rowIndex="4" GridPane.columnIndex="0" GridPane.columnSpan="3" />
   </children>
   <columnConstraints>
      <ColumnConstraints prefWidth="125.0" />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints prefHeight="50.0" />
   </rowConstraints>
   <padding>
      <Insets bottom="10.0" left="9.0" right="10.0" top="10.0" />
   </padding>

</GridPane>

Is having my testController control two different FXMLs a problem/a no go?

解决方案

When the FXMLLoader tries to load an fxml file, it will create new instance of the controller class defined with fx:controller in fxml file. Then it creates and maps the @FXML annotated fields with fx:id components in fxml file. Finally, it calls the controller's initialize() method. You can get the instantiated controller with fxmlloader.getController() after fxmlloader.load().

According to this basic work flow, the pitfall in your code is:
myMain.fxml's controller is TestController, but myMain.fxml does not contain TableColumns with fx:id colFirstName etc. So these fields are null, when the myMain.fxml has been loaded. As a result, there will be NPE in loadEmployeeForm() while trying to use these fields.

Move the TableView and TableColumns to frmEmployees.fxml's controller, and configure them (setCellValueFactory, initial data etc.) in this controller's initialize() method.

这篇关于JavaFX,为什么TableColumn为null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆