JavaFX TableView与SceneBuilder

JavaFX TableView与SceneBuilder

问题描述:

我有一个非常简单的类,它接受作业列表并尝试用它们填充TableView。我有这个工作没有使用FXML,但我现在正在尝试新的方法。我的问题是,JavaFX TableView与SceneBuilder

tView.getItems().addAll(jobList); 

返回一个空指针,但是如果我创建一个新的TableView,表中根本没有数据。

我相信我会出错的是使用在SceneBuilde中构造的TableView,并且没有正确初始化它,但是我很困惑我该如何做到这一点。这是我的InterFace方法类;

public class InterfaceMethods { 

    @FXML TableView<Job> tView; 

    @SuppressWarnings("unchecked") 
    public void populateTableView(Connection connection, Stage stage) throws Exception { 

     Parent root; 
     root = FXMLLoader.load(getClass().getResource("TableViewInterface.fxml")); 
     Scene scene = new Scene(root); 
     stage.setScene(scene); 

     JobDataAccessor jobAccessor = new JobDataAccessor(); 
     final String query = "SELECT * FROM progdb.adamJobs"; 
     List<Job> jobList = jobAccessor.getJobList(connection, query); 
     //System.out.println(query); 
     //System.out.println(connection); 
     tView.getItems().addAll(jobList); 
    } 
} 

这是我的MainApp类;

public class MainApp extends Application { 

private CheckUserDetails checkDetails; 
private String pString, username = System.getProperty("user.name"); 
private InterfaceMethods iMethods; 
private Connection connection; 
@FXML private Button submitButton; 
@FXML private PasswordField passField; 
@FXML private Label warnLabel; 

@Override 
public void start(Stage stage) throws Exception { 
    Parent root = FXMLLoader.load(getClass().getResource("MainInterface.fxml")); 
    Scene scene = new Scene(root); 
    stage.setScene(scene); 
    stage.show(); 
} 

@FXML 
private void loginCheck() throws Exception { 
    checkDetails = new CheckUserDetails(); 
    pString = new String(); 
    pString = passField.getText(); 
    System.out.println(pString); 
    if (checkDetails.checkUserDetails(pString, username) != null) { 
     setConnection(checkDetails.connection); 
     handleTableView(); 
    } else { 
     warnLabel.setVisible(true); 
    } 
} 

@FXML 
public void handleTableView() throws Exception { 
    iMethods = new InterfaceMethods(); 

    Stage stage = (Stage) submitButton.getScene().getWindow(); 

    connection = getConnection(); 

    iMethods.populateTableView(connection, stage); 
} 

public static void main(String[] args) { 
    launch(args); 
} 

最后,这里是我的两个FXML文件之一,其中包含TableView;

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

<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.GridPane?> 

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.InterfaceMethods"> 
    <children> 
     <TableView fx:id="tView" layoutX="17.0" layoutY="19.0" prefHeight="347.0" prefWidth="570.0"> 
     <columns> 
      <TableColumn prefWidth="75.0" text="CaseNO." /> 
      <TableColumn prefWidth="75.0" text="Case Notes" /> 
      <TableColumn prefWidth="75.0" text="Date Created" /> 
      <TableColumn prefWidth="75.0" text="Deadline" /> 
      <TableColumn prefWidth="75.0" text="Priority" /> 
      <TableColumn prefWidth="75.0" text="Completed" /> 
     </columns> 
     <columnResizePolicy> 
      <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> 
     </columnResizePolicy> 
     </TableView> 
    </children> 
</AnchorPane> 

getJobList方法(在不同的类中);

public List<Job> getJobList(final Connection connection, final String query) throws SQLException { 
    try (Statement stmnt = connection.createStatement(); ResultSet rs = stmnt.executeQuery(query);) { 
     jobList = new ArrayList<>(); 
     System.out.println(connection); 
     System.out.println(query); 
     while (rs.next()) { 
      caseNumber = rs.getString("CaseNO"); 
      caseNotes = rs.getString("CaseNotes"); 
      dateCreated = rs.getString("DateCreated"); 
      deadlineDate = rs.getString("Deadline"); 
      prioritySetting = rs.getInt("Priority"); 
      completedSetting = rs.getString("Completed"); 
      job = new Job(caseNumber, caseNotes, dateCreated, deadlineDate, prioritySetting, completedSetting); 
      jobList.add(job); 
     } 
     return jobList; 
    } 
} 
+0

FXML文件中的TableView的fx:id应该与conrtoller类中的名称相同,即“的tableView”。是不是,检查它? –

+0

这绝对是一样的。我也会用我的控制器类更新这个问题。 – jbanks

+0

用javafx.fxml.Initializableclass扩展控制器类。 – Hareesh

您需要定义控制器为您FXML。

例如您FXML的部分是: -

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="288.0" prefWidth="293.0" xmlns:fx="http://javafx.com/fxml"> 
<children> 
    <TableView fx:id="tableView" layoutX="35.0" layoutY="28.0" prefHeight="200.0" prefWidth="227.0"> 
    <columns> 
     <!-- Columns for table view--> 
    </columns> 
    </TableView> 
</children> 
</AnchorPane> 

1)您FXML页面一样创建一个控制器: - 在你的控制器

fx:controller="com.code.Controller" 

2)现在,你可以做如下: -

package com.code; 

    public class Controller implements Initializable { 

     @FXML private TableView<User> tableView; 
+0

感谢您的评论阿米特。我已经检查过,我的FXML已经有一个控制器:'fx:controller =“application.MainApp”'。现在在我的控制器(MainApp)中我有:'@FXML private TableView tableView;'然后尝试调用该方法。 – jbanks

+0

@jbanks,但它说在问题中你的控制器类名是“InterfaceMethods”。 –

+0

@Uluk Biy道歉我的错误,控制器确实是InterfaceMethods(我试过不同的控制器,现在改回fx:controller =“application.InterfaceMethods”),我仍然得到空指针异常,非常令人沮丧。不太确定我出错的地方。 – jbanks

控制器类的所有@FXML注释字段是在加载fxml文件时由FXMLLoader实例化,该文件的fx:controller等于该控制器类或由fxmlLoader.setController()设置的类。如果您自己实例化控制器类,则这些@FXML注释的字段将为空。在FXML文件控制器:使用setController(),而不是FX所以在这里样本方法

MainApp

public class MainApp extends Application 
{ 
    @Override 
    public void start(Stage stage) throws Exception 
    { 
     MainController mainController = new MainController(getConnection()); 

     Scene scene = new Scene(mainController.getLayout()); 

     stage.setScene(scene); 
     stage.show(); 
    } 


    public static void main(String[] args) 
    { 
     launch(args); 
    } 
} 

MainController

public class MainController implements Initializable 
{ 

    @FXML 
    private Label label; 

    private Parent layout; 

    private Connection connection; 


    public MainController(Connection connection) 
    { 
     this.connection = connection; 

     FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Main.fxml")); 
     fxmlLoader.setController(this); 
     try 
     { 
      layout = (Parent) fxmlLoader.load(); 
     } 
     catch (IOException exception) 
     { 
      throw new RuntimeException(exception); 
     } 
    } 


    public Parent getLayout() 
    { 
     return layout; 
    } 


    @FXML 
    private void handleTableView(ActionEvent event) 
    { 
     InterfaceMethods iMethods = new InterfaceMethods(connection); 
     label.getScene().setRoot(iMethods.getLayout()); 
     label.getScene().getWindow().sizeToScene(); 
    } 


    @Override 
    public void initialize(URL url, ResourceBundle rb) 
    { 
     // do work with @FXML annotated fields in here 
     label.setText("Initial data!"); 
    } 

} 

Main.fxml

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

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1"> 
    <children> 
     <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleTableView" fx:id="button" /> 
     <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" /> 
    </children> 
</AnchorPane> 

InterfaceMethods

public class InterfaceMethods implements Initializable 
{ 

    @FXML 
    TableView<Job> tView; 

    private Parent layout; 

    private Connection connection; 


    public MainController(Connection connection) 
    { 
     this.connection = connection; 

     FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("TableViewInterface.fxml")); 
     fxmlLoader.setController(this); 
     try 
     { 
      layout = (Parent) fxmlLoader.load(); 
     } 
     catch (IOException exception) 
     { 
      throw new RuntimeException(exception); 
     } 
    } 


    public Parent getLayout() 
    { 
     return layout; 
    } 

    @Override 
    public void initialize(URL url, ResourceBundle rb) 
    { 
     // do work with @FXML annotated fields in here 
     tView.setItems(...); 
    } 

} 

注意Main.fxml和TableViewInterface.fxml没有在它fx:controller

+0

我不确定我100%了解这个问题,但我感谢您的帮助。我将继续阅读教程并观看视频,希望更好地理解这种情况。 – jbanks

+0

问题是iMethods = new InterfaceMethods();在你的代码中。如果您使用的是fx:conrtoller方法,您应该使用FXMLloader并从fxmlloader中获取conrtoller实例,而不是自己启动它。如果没有,那么你可以按照我的回答使用setConrtoller()方法并自己初始化conrtoller类。 –

+0

@jbanks,另一个问题是,在populateTableView()方法中,您正在加载“TableViewInterface。fxml“,这将创建新的InterfaceMethods并填充其tView字段,而** current **实例的tView将为null,这就是为什么NPE, –