[英]javafx.fxml.LoadException when trying to display a list of objects in a TableView JavaFX
我正在嘗試在 JavaFX 表中顯示對象列表,但是在循環遍歷要添加到表中的對象時,我一直遇到 JavaFX 異常,有人知道可能導致這種情況的原因嗎,我嘗試了幾種不同的 ObservableLists 實現但他們都看到產生相同的結果,我的結論是 class 或 .fxml 文件可能存在錯誤。 提前致謝。
JavaFX:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="HomePageController">
<left>
<AnchorPane prefHeight="400.0" prefWidth="200.0" style="-fx-background-color: #c7a4ff;" BorderPane.alignment="CENTER">
<children>
<Label fx:id="userLabel" alignment="TOP_CENTER" contentDisplay="CENTER" text="Hello <User>" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="Segoe UI Semilight" size="24.0" />
</font>
<padding>
<Insets bottom="10.0" left="25.0" right="25.0" top="10.0" />
</padding>
</Label>
<padding>
<Insets bottom="10.0" left="25.0" right="25.0" top="10.0" />
</padding>
</Label>
<Button layoutY="60.0" mnemonicParsing="false" onAction="#MenuSwitch" prefHeight="50.0" prefWidth="200.0" style="-fx-background-color: #aa80ff;" text="Home" textFill="WHITE">
<font>
<Font size="14.0" />
</font>
</Button>
<Button layoutY="120.0" mnemonicParsing="false" onAction="#MenuSwitch" prefHeight="50.0" prefWidth="200.0" style="-fx-background-color: #aa80ff;" text="Diet" textFill="WHITE">
<font>
<Font size="14.0" />
</font>
</Button>
<Button layoutY="180.0" mnemonicParsing="false" onAction="#MenuSwitch" prefHeight="50.0" prefWidth="200.0" style="-fx-background-color: #aa80ff;" text="Workout" textFill="WHITE">
<font>
<Font size="14.0" />
</font>
</Button>
<Button layoutY="240.0" mnemonicParsing="false" onAction="#MenuSwitch" prefHeight="50.0" prefWidth="200.0" style="-fx-background-color: #aa80ff;" text="Groups" textFill="WHITE">
<font>
<Font size="14.0" />
</font>
</Button>
<Button layoutY="300.0" mnemonicParsing="false" onAction="#MenuSwitch" prefHeight="50.0" prefWidth="200.0" style="-fx-background-color: #aa80ff;" text="User Information" textFill="WHITE">
<font>
<Font size="14.0" />
</font>
</Button>
</children>
</AnchorPane>
</left>
<right>
<AnchorPane prefHeight="400.0" prefWidth="394.0" BorderPane.alignment="CENTER">
<children>
<Label alignment="TOP_CENTER" contentDisplay="CENTER" layoutX="148.0" text="Home" textAlignment="CENTER" textFill="#aa80ff">
<font>
<Font name="Segoe UI Semilight" size="24.0" />
</font>
<padding>
<Insets bottom="10.0" left="10.0" right="25.0" top="10.0" />
</padding>
</Label>
<Label alignment="TOP_CENTER" contentDisplay="CENTER" layoutX="14.0" layoutY="55.0" text="My Goals" textAlignment="CENTER" textFill="#aa80ff">
<font>
<Font name="Segoe UI Semilight" size="18.0" />
</font>
<padding>
<Insets bottom="10.0" left="10.0" right="25.0" top="10.0" />
</padding>
</Label>
<TableView fx:id="tbData" layoutX="14.0" layoutY="102.0" prefHeight="200.0" prefWidth="360.0" style="-fx-background-color: #ffffff;">
<columns>
<TableColumn fx:id="goalName" prefWidth="160.0" text="Name" />
<TableColumn fx:id="goalDate" prefWidth="50.0" text="Date" />
<TableColumn fx:id="goalStatus" prefWidth="75.0" text="Status" />
<TableColumn fx:id="goalGroups" prefWidth="10.0" text="Groups"/>
</columns>
</TableView>
</children>
</AnchorPane>
</right>
<bottom>
<AnchorPane prefHeight="50.0" prefWidth="600.0" style="-fx-background-color: #c7a4ff;" BorderPane.alignment="CENTER">
<children>
<ImageView fitHeight="30.0" fitWidth="30.0" layoutX="380.0" layoutY="10.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@img/add_box.png" />
</image>
</ImageView>
<Button graphicTextGap="0.0" layoutX="380.0" layoutY="10.0" mnemonicParsing="false" onAction="#openSelectGoalTypePage" opacity="0.0" prefHeight="30.0" prefWidth="30.0" />
<ImageView fitHeight="30.0" fitWidth="30.0" layoutX="300.0" layoutY="10.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@img/mode_edit.png" />
</image>
</ImageView>
<Button graphicTextGap="0.0" layoutX="300.0" layoutY="10.0" mnemonicParsing="false" onAction="#openEditGoalPage" opacity="0.0" prefHeight="30.0" prefWidth="30.0" />
<ImageView fitHeight="30.0" fitWidth="30.0" layoutX="460.0" layoutY="10.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@img/delete.png" />
</image>
</ImageView>
<Button graphicTextGap="0.0" layoutX="460.0" layoutY="10.0" mnemonicParsing="false" onAction="#removeTableItem" opacity="0.0" prefHeight="30.0" prefWidth="30.0" />
</children>
</AnchorPane>
</bottom>
</BorderPane>
Controller:
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class HomePageController extends BaseController implements Initializable {
@FXML
private TableView<Goal> tbData = new TableView<>();
@FXML
public TableColumn<Goal, String> goalName;
@FXML
public TableColumn<Goal, String> goalDate;
@FXML
public TableColumn<Goal, String> goalStatus;
@FXML
public TableColumn<Goal, String> goalGroups;
/*@FXML
private Label userLabel;*/
//allow user to select a table item/row and delete it using the delete button
public void removeTableItem(){
}
public void openSelectGoalTypePage(javafx.event.ActionEvent actionEvent) throws IOException {
root = FXMLLoader.load(getClass().getResource("SelectGoalType.fxml"));
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public void openAddGoalPage(javafx.event.ActionEvent actionEvent) throws IOException {
//if user selects weight goal then open AddWeightGoal page
//else if user selects workout goal then open AddWorkoutGoal page
root = FXMLLoader.load(getClass().getResource("AddWeightGoal.fxml"));
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public void openEditGoalPage(javafx.event.ActionEvent actionEvent) throws IOException {
root = FXMLLoader.load(getClass().getResource("EditGoal.fxml"));
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
tbData = new TableView<>();
TableColumn<Goal, String> goalName = new TableColumn<>("GoalName");
goalName.setCellValueFactory(new PropertyValueFactory<>("goalName"));
TableColumn<Goal, String> goalDate = new TableColumn<>("GoalDate");
goalDate.setCellValueFactory(new PropertyValueFactory<>("goalDate"));
TableColumn<Goal, String> goalStatus = new TableColumn<>("GoalStatus");
goalDate.setCellValueFactory(new PropertyValueFactory<>("goalStatus"));
TableColumn<Goal, String> goalGroups = new TableColumn<>("GoalGroups");
goalGroups.setCellValueFactory(new PropertyValueFactory<>("goalGroups"));
tbData.getColumns().add(goalName);
tbData.getColumns().add(goalDate);
tbData.getColumns().add(goalStatus);
tbData.getColumns().add(goalGroups);
tbData.setItems(getGoals());
}
private ObservableList<Goal> getGoals(){
ObservableList<Goal> goals = FXCollections.observableArrayList();
for(int i = 0; i < user.getGoals().size(); i++){
goals.add(user.getGoals().get(i));
}
return goals;
}
}
目標 Class:
import java.io.Serial;
import java.io.Serializable;
public class Goal implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
public String getGoalName() {
return goalName;
}
public void setGoalName(String goalName) {
this.goalName = goalName;
}
public String getGoalDate() {
return goalDate;
}
public void setGoalDate(String goalDate) {
this.goalDate = goalDate;
}
public String getGoalStatus() {
return goalStatus;
}
public void setGoalStatus(String goalStatus) {
this.goalStatus = goalStatus;
}
public String getGoalGroups() {
return goalGroups;
}
public void setGoalGroups(String goalGroups) {
this.goalGroups = goalGroups;
}
public Goal(String goalName, String goalDate, String goalStatus, String goalGroups) {
this.goalName = goalName;
this.goalDate = goalDate;
this.goalStatus = goalStatus;
this.goalGroups = goalGroups;
}
String goalName;
String goalDate;
String goalStatus;
String goalGroups;
}
編輯:
I've done some more debugging and it seems when I surround it with a try-catch block it's pointing to my user object from the base controller being null, even though I believe I pass it to the controller here's the base controller which holds the user object ,以及我用來傳遞用戶 object 的調用(在作為參數傳遞之前確認用戶很好)。 我似乎得到的唯一堆棧跟蹤是加載程序,這是來自嘗試捕獲: java.lang.NullPointerException: Cannot invoke "User.getGoals()" because "this.user" is null
:
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import java.io.IOException;
public class BaseController {
User user;
Parent root;
Stage stage;
Scene scene;
@FXML
Label userLabel;
//default constructor
public BaseController(){
}
void setUser(User user){
this.user = user;
userLabel.setText(user.getUsername());
}
//connect to current user once logged in
/*
public BaseController(User user){
displayUsername(User);
}*/
//display current logged in user's first name
/*
private void displayUsername(User user){
userLabel.setText(user.firstName);
}*/
/**
* Menu Functions just in case
*/
// public void openHomePage(javafx.event.ActionEvent actionEvent) throws IOException {
// root = FXMLLoader.load(getClass().getResource("HomePage.fxml"));
// stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
// scene = new Scene(root);
// stage.setScene(scene);
// stage.show();
// }
//
// public void openDietPage(javafx.event.ActionEvent actionEvent) throws IOException {
// root = FXMLLoader.load(getClass().getResource("DietPage.fxml"));
// stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
// scene = new Scene(root);
// stage.setScene(scene);
// stage.show();
// }
//
// public void openWorkoutPage(javafx.event.ActionEvent actionEvent) throws IOException {
// root = FXMLLoader.load(getClass().getResource("WorkoutPage.fxml"));
// stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
// scene = new Scene(root);
// stage.setScene(scene);
// stage.show();
// }
//
// public void openGroupsPage(javafx.event.ActionEvent actionEvent) throws IOException {
// root = FXMLLoader.load(getClass().getResource("GroupsPage.fxml"));
// stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
// scene = new Scene(root);
// stage.setScene(scene);
// stage.show();
// }
//
// public void openUserPage(javafx.event.ActionEvent actionEvent) throws IOException {
// root = FXMLLoader.load(getClass().getResource("UserPage.fxml"));
// stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
// scene = new Scene(root);
// stage.setScene(scene);
// stage.show();
// }
public void MenuSwitch(javafx.event.ActionEvent actionEvent) throws IOException{
String text = ((Button)actionEvent.getSource()).getText();
String filename="";
switch(text){
case "Home":
filename="HomePage.fxml";break;
case "Diet":
filename="DietPage.fxml";break;
case "Workout":
filename="WorkoutPage.fxml";break;
case "Groups":
filename="GroupsPage.fxml";break;
case "User Information":
filename="UserPage.fxml";break;
case "Edit group":
filename="EditGroupPage.fxml"; break;
case "Create group":
filename="CreateGroupPage.fxml";break;
case "Add Diet Item":
filename="AddDietItemPage.fxml"; break;
case "EditWorkoutPage":
filename="EditWorkoutPage.fxml";break;
case "AddWorkoutPage":
filename="AddWorkoutPage.fxml";break;
case "EditUserPage":
filename="EditUserPage.fxml";break;
}
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(filename));
Parent root = (Parent) fxmlLoader.load();
BaseController baseController = fxmlLoader.getController();
System.out.println(user);
baseController.setUser(user);
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
從之前通過用戶object的controller:
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("HomePage.fxml"));
Parent root = (Parent) fxmlLoader.load();
HomePageController controller = fxmlLoader.getController();
controller.setUser(newUser);
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
謝謝!
編輯二:完整堆棧跟蹤:
java.lang.NullPointerException: Cannot invoke "User.getGoals()" because "this.user" is null
java.lang.NullPointerException: Cannot invoke "User.getGoals()" because "this.user" is null
at HomePageController.initialize(HomePageController.java:75)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2655)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2517)
at UserLoginController.login(UserLoginController.java:108)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1857)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1729)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8886)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:203)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:208)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3856)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2584)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:409)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:299)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:447)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:446)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
at java.base/java.lang.Thread.run(Thread.java:832)
java.sql.SQLException: The prepared statement has been finalized
在執行FXMLLoader.load()
期間會調用控制器的initialize()
方法,因此在調用setUser(...)
之前會調用initialize()
和getGoals()
)。 因此,當您嘗試調用user.getGoals()
時, user
是 null 。
要在您設置的結構中解決此問題,您需要在setUser(...)
時填充表列表。 您可以在子類中使用重寫的setUser(...)
方法來做到這一點。
另請注意,初始化@FXML
的字段始終是錯誤的(因為它們由FXMLLoader
初始化為 FXML 文件中定義的元素)。 所以你的 controller 應該是這樣的:
public class HomePageController extends BaseController implements Initializable {
@FXML
private TableView<Goal> tbData ;
@FXML
public TableColumn<Goal, String> goalName;
@FXML
public TableColumn<Goal, String> goalDate;
@FXML
public TableColumn<Goal, String> goalStatus;
@FXML
public TableColumn<Goal, String> goalGroups;
/*@FXML
private Label userLabel;*/
//allow user to select a table item/row and delete it using the delete button
public void removeTableItem(){
}
public void openSelectGoalTypePage(javafx.event.ActionEvent actionEvent) throws IOException {
root = FXMLLoader.load(getClass().getResource("SelectGoalType.fxml"));
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public void openAddGoalPage(javafx.event.ActionEvent actionEvent) throws IOException {
//if user selects weight goal then open AddWeightGoal page
//else if user selects workout goal then open AddWorkoutGoal page
root = FXMLLoader.load(getClass().getResource("AddWeightGoal.fxml"));
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public void openEditGoalPage(javafx.event.ActionEvent actionEvent) throws IOException {
root = FXMLLoader.load(getClass().getResource("EditGoal.fxml"));
stage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
goalName.setCellValueFactory(new PropertyValueFactory<>("goalName"));
goalDate.setCellValueFactory(new PropertyValueFactory<>("goalDate"));
goalDate.setCellValueFactory(new PropertyValueFactory<>("goalStatus"));
goalGroups.setCellValueFactory(new PropertyValueFactory<>("goalGroups"));
}
@Override
void setUser(User user){
super.setUser(user);
tbData.setItems(getGoals());
}
private ObservableList<Goal> getGoals(){
return FXCollections.observableList(user.getGoals());
}
}
更標准的方法是使用 MVC 類型的設計,其中用戶由ObjectProperty<User>
表示,您可以觀察它的變化。 例如
public class BaseController {
private final ObjectProperty<User> user;
// ...
//default constructor
public BaseController(){
user = new SimpleObjectProperty();
user.addListener((obs, oldUser, newUser) ->
userLabel.setText(newUser == null ? "" : newUser.getUsername()));
}
public ObjectProperty<User> userProperty() {
return user ;
}
public final User getUser() {
return userProperty().get();
}
public final void setUser(User user) {
userProperty().set(user);
}
// ...
}
和
public class HomePageController extends BaseController implements Initializable {
@FXML
private TableView<Goal> tbData ;
@FXML
public TableColumn<Goal, String> goalName;
@FXML
public TableColumn<Goal, String> goalDate;
@FXML
public TableColumn<Goal, String> goalStatus;
@FXML
public TableColumn<Goal, String> goalGroups;
public HomePageController() {
userProperty().addListener((obs, oldUser, newUser) -> {
if (newUser == null) {
tbData.setItems(FXCollections.observableArrayList());
} else {
tbData.setItems(getGoals());
}
});
}
// ...
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
goalName.setCellValueFactory(new PropertyValueFactory<>("goalName"));
goalDate.setCellValueFactory(new PropertyValueFactory<>("goalDate"));
goalDate.setCellValueFactory(new PropertyValueFactory<>("goalStatus"));
goalGroups.setCellValueFactory(new PropertyValueFactory<>("goalGroups"));
}
private ObservableList<Goal> getGoals(){
return FXCollections.observableList(user.getGoals());
}
}
通常在這里, user
不是您需要觀察的唯一值,因此它將被分解到某處的 model 中。 例如,參見應用 MVC 與 JavaFx
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.