假设我有两个模型。老师和学生,每个学生可以有一位老师(不是几位)。所以我想在我的学生面板上有一个组合框,我可以在其中选择一位老师。
两个模型也存储在数据库中,我只希望教师的数据库 ID 出现在学生的模型中,但在组合框中应显示教师的姓名。
模型也应该绑定(bind)到组合框,所以如果有人改变了组合框中的老师,(学生的)模型也应该被刷新。使用文本字段,我可以将它们绑定(bind)到 StringProperty 对象,但在这种情况下,我需要将组合框项 (Teacher.java) 绑定(bind)到我的 Student.java 中的整数属性。
我还考虑过将教师模型作为学生类(class)中的一个属性,但我认为这无济于事,因为那样我就需要将组合框项 (teacher.java) 与学生模型中的教师对象绑定(bind)但只能绑定(bind) property 对象。
Teacher.java
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Teacher {
private Integer databaseID;
private StringProperty name = new SimpleStringProperty();
private IntegerProperty age = new SimpleIntegerProperty();
public Teacher (Integer databaseID) {
// load data from database and fill into model
}
public void store() {
// write model to database
}
// getters and setters ...
@Override
public String toString() {
return name.get();
}
@Override
public boolean equals(Object obj) {
// compare databaseIDs ...
return true;
}
}
Student.java
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Student {
private Integer databaseID;
private StringProperty name = new SimpleStringProperty();
private Integer teacherID;
public Student (Integer databaseID) {
// load data from database and fill into model
}
public void store() {
// write model to database
}
// getters and setters ...
@Override
public String toString() {
return name.get();
}
@Override
public boolean equals(Object obj) {
// compare databaseIDs ...
return true;
}
}
应用程序.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class TestApplication extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Student student = new Student(4711);
ComboBox<Teacher> teachers = new ComboBox<Teacher>();
fillTeacherComboBox(teachers);
// TODO: select the teacher from the student by default
// FIXME: Binding student.databaseID <--> ComboBox-Item.databaseID
StackPane root = new StackPane();
root.getChildren().add(teachers);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
private void fillTeacherComboBox(ComboBox<Teacher> teachers) {
// TODO: Load data from database and fill teacher combo box
}
}
请您参考如下方法:
我会(至少)对此处的设计进行一项更改:将对 Teacher
对象的引用存储在 Student
对象中(并使用 JavaFX 属性来执行它):
public class Student {
private Integer databaseID;
private StringProperty name = new SimpleStringProperty();
private ObjectProperty<Teacher> teacher = new SimpleObjectProperty<>();
public Student (Integer databaseID) {
// load data from database and fill into model
/* Just as an aside, it is really bad practice to include
database code in your domain objects as you suggest here.
You should create a separate class that manages the database
code (a DataAccessObject) and the domain objects Student and
Teacher should be completely agnostic as to the mechanism by
which they are persisted (or even whether they are persisted).*/
}
public void store() {
// write model to database
// see above comment.
}
// getters and setters ...
public ObjectProperty<Teacher> teacherProperty() {
return teacher ;
}
public final Teacher getTeacher() {
return teacherProperty().get();
}
public final void setTeacher(Teacher teacher) {
teacherProperty().set(teacher);
}
@Override
public String toString() {
return name.get();
}
@Override
public boolean equals(Object obj) {
// compare databaseIDs ...
return true;
}
}
现在你只需要做
Student student = ... ;
ComboBox<Teacher> teachers = new ComboBox<>();
// populate combo box...
teachers.valueProperty().bindBidirectional(student.teacherProperty());