使用对象列表时设置选择框值

Hal*_*cht 2 java javafx observable

我正在尝试设置我的 choiceBox 的值。

当使用像这样的纯字符串时它可以工作:

choiceBox.getItems.setAll(FXCollections.observableArrayList("a","b","c"));
choiceBox.setValue("a");
Run Code Online (Sandbox Code Playgroud)

但当使用类填充和设置 choiceBox 时,它不会设置值(并且没有错误)

ObservableList<Course> items = FXCollections.observableArrayList();
items.add(Course.getAll());

choiceBox.getItems().setAll(items);
choiceBox.setValue(schedule.getCourse());
Run Code Online (Sandbox Code Playgroud)

也尝试使用shedule.getCourse().toString(),因为 choiceBox 使用 toString 方法来显示课程。

需要我的对象的哪一部分ChoiceBox

我的课程班级:

public class Course {

// Property Value Factory
public static final String PVF_NAME = "name";

private String name;

// == constructors ==

public Course(String name) {
    this.name = name;
}

// == public methods ==

@Override
public String toString() {
    return name;
}

public static Course fromString(String line) {
    return new Course(line);
}

// Getters & Setters

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
Run Code Online (Sandbox Code Playgroud)

}

Zep*_*hyr 6

您需要重写toString()对象的方法。将ChoiceBox使用该值作为选项列表。

ChoiceBox从那里,您需要通过传递对 中所需值的引用Course来选择 的值coursesList

下面是一个简单的 MCVE 来演示:

课程.java:

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Course {

    private StringProperty courseName = new SimpleStringProperty();

    public Course(String courseName) {
        this.courseName.set(courseName);
    }

    public String getCourseName() {
        return courseName.get();
    }

    public StringProperty courseNameProperty() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName.set(courseName);
    }

    // The ChoiceBox uses the toString() method of our object to display options in the dropdown.
    // We need to override this method to return something more helpful.
    @Override
    public String toString() {
        return courseName.get();
    }
}
Run Code Online (Sandbox Code Playgroud)

主要.java:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Create the ChoiceBox
        ChoiceBox<Course> cbCourses = new ChoiceBox<>();

        // Sample list of Courses
        ObservableList<Course> coursesList = FXCollections.observableArrayList();

        // Set the list of Course items to the ChoiceBox
        cbCourses.setItems(coursesList);

        // Add the ChoiceBox to our root layout
        root.getChildren().add(cbCourses);

        // Now, let's add sample data to our list
        coursesList.addAll(
                new Course("Math"),
                new Course("History"),
                new Course("Science"),
                new Course("Geography")
        );

        // Now we can select our value. For this sample, we'll choose the 3rd item in the coursesList
        cbCourses.setValue(coursesList.get(2));

        // Show the Stage
        primaryStage.setWidth(300);
        primaryStage.setHeight(200);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

在此输入图像描述


编辑

要按名称选择Course,您将需要一个辅助方法来CoursecoursesList.

使用 Java 8 流 API:

    private Course getCourseByName(String name, List<Course> courseList) {

    // This basically filters the list based on your filter criteria and returns the first match,
    // or null if none were found.
    return courseList.stream().filter(course ->
            course.getCourseName().equalsIgnoreCase(name)).findFirst().orElse(null);
}
Run Code Online (Sandbox Code Playgroud)

之前的 Java 版本:

    private Course getCourseByName(String name, List<Course> courseList) {

    // Loop through all courses and compare the name. Return the Course if a match is found or null if not
    for (Course course : courseList) {
        if (name.equalsIgnoreCase(course.getCourseName())) {
            return course;
        }
    }

    return null;
}
Run Code Online (Sandbox Code Playgroud)

您现在可以使用选择值cbCourses.setValue(getCourseByName("History", coursesList));


编辑#2:

为了平息克利奥帕特拉的批评,我将发布一种更“正确”的方法来更新对象的显示值Course。虽然我认为在大多数简单应用程序中重写没有任何问题toString(),特别是如果您的设计方式使得对象只需要一种字符串表示形式,但我将在此处添加另一种方法。

不要toString()直接在Course对象中覆盖该方法,而是在其自身上设置转换器ComboBox

    cbCourses.setConverter(new StringConverter<Course>() {
        @Override
        public String toString(Course object) {
            return object.getCourseName();
        }

        @Override
        public Course fromString(String string) {
            return null;
        }
    });
Run Code Online (Sandbox Code Playgroud)

然而,我确实认为这在非​​常简单的应用程序中是不必要的,并且在我自己的实际项目中也不需要它。然而,这是“正确”的方式。

  • 不,完全错误 - 出于应用程序原因永远不要覆盖 toString (如果同一项目显示在具有不同可视化要求的不同上下文中,您会怎么做?)相反,使用带有 stringconverter 的配置选项框 (2认同)