带有 SceneBuilder 的 JavaFX TableView
JavaFX TableView With SceneBuilder
我有一个非常简单的 class,它获取作业列表并尝试用它们填充 TableView。我在不使用 FXML 的情况下工作,但我现在正在尝试新方法。我遇到的问题是;
tView.getItems().addAll(jobList);
returns 一个空指针,但是如果我创建一个新的 TableView,table 中根本没有数据。
我认为我出错的地方在于使用了在 SceneBuilder 中构建的 TableView 而没有正确初始化它,但是我对如何执行此操作感到困惑。这是我的接口方法 class;
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 class;
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 方法(内部不同class);
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;
}
}
You need to define the controller for your 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;
控制器 class 的所有 @FXML 注释字段在加载 fx:controller
等于该控制器 class 或 class 的 fxml 文件时由 FXMLLoader 实例化您通过 fxmlLoader.setController() 设置。如果您自己实例化控制器 class,这些带有 @FXML 注释的字段将为空。所以这里是在 fxml 文件中使用 setController() 而不是 fx:controller 的示例方法:
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 );
}
}
主控制器
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>
接口方法
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
。
我有一个非常简单的 class,它获取作业列表并尝试用它们填充 TableView。我在不使用 FXML 的情况下工作,但我现在正在尝试新方法。我遇到的问题是;
tView.getItems().addAll(jobList);
returns 一个空指针,但是如果我创建一个新的 TableView,table 中根本没有数据。
我认为我出错的地方在于使用了在 SceneBuilder 中构建的 TableView 而没有正确初始化它,但是我对如何执行此操作感到困惑。这是我的接口方法 class;
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 class;
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 方法(内部不同class);
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;
}
}
You need to define the controller for your 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;
控制器 class 的所有 @FXML 注释字段在加载 fx:controller
等于该控制器 class 或 class 的 fxml 文件时由 FXMLLoader 实例化您通过 fxmlLoader.setController() 设置。如果您自己实例化控制器 class,这些带有 @FXML 注释的字段将为空。所以这里是在 fxml 文件中使用 setController() 而不是 fx:controller 的示例方法:
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 );
}
}
主控制器
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>
接口方法
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
。