简体   繁体   English

JavaFX,为什么TableColumn为null?

[英]JavaFX, why is TableColumn null?

As you will see I am a massive noob when it comes to Java and Javafx. 正如您将看到的那样,在Java和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. 我花了很多时间阅读(各种论坛帖子和Tut),并试图弄清楚自己在哪里得到了这个问题,但是现在我要发表自己的观点来征求了解他们业务的人的反馈。

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!! 到目前为止,这是我所拥有的(我的FXML和我的两个类)任何指针都很棒!

My 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>

Now the Employee class I have; 现在我有了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);
}

} }

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

If I add in lines such as; 如果我添加如下行: TableColumn colFirstName = new TableColumn("firstName"); TableColumn colFirstName =新的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? 对于我的每个列和表名,它都是这样工作的(即,它不会向我抛出错误消息),但是然后我没有将任何数据加载到tableview中,因为我认为那是我创建的新tableView不使用从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; 更新1;

The method for load employee form is called from a button on myMain.fxml; 从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? 让我的testController控制两个不同的FXML是一个问题/行不通吗?

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. FXMLLoader尝试加载fxml文件时,它将在fxml文件中创建使用fx:controller定义的控制器类的新实例。 Then it creates and maps the @FXML annotated fields with fx:id components in fxml file. 然后,它在fxml文件中使用fx:id组件创建并映射@FXML带注释的字段。 Finally, it calls the controller's initialize() method. 最后,它调用控制器的initialize()方法。 You can get the instantiated controller with fxmlloader.getController() after fxmlloader.load(). 您可以在fxmlloader.load()之后使用fxmlloader.getController()获取实例化的控制器。

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. myMain.fxml的控制器是TestController,但myMain.fxml不包含带有fx:id colFirstName等的TableColumns。因此,在加载myMain.fxml时,这些字段为null。 As a result, there will be NPE in loadEmployeeForm() while trying to use these fields. 结果,尝试使用这些字段时,loadEmployeeForm()中将存在NPE。

Move the TableView and TableColumns to frmEmployees.fxml's controller, and configure them (setCellValueFactory, initial data etc.) in this controller's initialize() method. 将TableView和TableColumns移动到frmEmployees.fxml的控制器,并在此控制器的initialize()方法中对其进行配置(setCellValueFactory,初始数据等)。

You never use your Employee(String, String, String) constructor. 您永远不会使用Employee(String, String, String)构造函数。 This constructor initializes the firstName , lastName , and email . 此构造函数初始化firstNamelastNameemail Otherwise, your references will point to nothing. 否则,您的引用将毫无意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM