JavaFX ComboBox binding

折月煮酒 提交于 2020-02-04 03:57:09

问题


lets say that I have two models. Teacher and Students and each Student can have one Teacher (not several). So I want to have an combo box on my student pane where I can select one teacher.

Both models are also stored in the database and I want only the database ID of the teacher to be in the model of the student but inside the combo box the name of the teacher should appear.

Also the model should be binded to the combo box, so if somebody changed the teacher in the combobox, the model (of the student) should be refreshed as well. With textfields I can bind them to StringProperty objects, but in this case I need to bind the comboxbox item (Teacher.java) to an interger-property inside my Student.java.

I also thought about having the teacher-model as a property inside my student class, but I think that will not help, because then I need to bind the combobox item (teacher.java) with a teacher object inside my student model but only property objects can be binded.

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;
    }
}

Application.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
    }


}

回答1:


I would make (at least) one change to the design here: store a reference to the Teacher object in the Student object (and use a JavaFX property to do it):

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;
    }
}

And now you just do

Student student = ... ;
ComboBox<Teacher> teachers = new ComboBox<>();
// populate combo box...
teachers.valueProperty().bindBidirectional(student.teacherProperty());



回答2:


You Can try one of these:(worked for me)

semesterBoxDay.selectionModelProperty().bind(semesterBox.selectionModelProperty());

When change 1st one 2d one change and verse happen,I know this is odd i don't know if there's explain for that (it work like bindBidirectional() here)

semesterBoxDay.valueProperty().bindBidirectional(semesterBox.valueProperty()); 

when i use bind() here i can't change the 2d one value until i change the 1st one

(i think because the 2d one value will never change untill u set it but i don't know why not change if click the new item in list). if anyone have answer for these problems i hope he could write them .



来源:https://stackoverflow.com/questions/34506662/javafx-combobox-binding

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!