javafx 如何将可用枚举列表添加到 ComboBoxTableCell?
javafx how do I add a list of available enums to ComboBoxTableCell?
无法弄清楚如何使用 ComboBox 将枚举列表添加到 table。目前代码无法编译,它在 StringConverter 的 grade.toString() 中失败。
以下是我正在使用的基本示例。最终我希望能够做三件事:
显示包含所有可用枚举的组合框
用当前成绩预填充它,如果有的话。
能够更改选择并使用新选择更新学生的对象。
有人可以帮忙吗?
public class App extends Application {
@Override
public void start(Stage stage) throws Exception {
try {
StackPane root = new StackPane();
TableView<Student> tbl = new TableView<>();
TableColumn<Student, Grade> col = new TableColumn<>("Grade");
ObservableList<Grade> grades = FXCollections.observableArrayList(Grade.values());
col.setCellFactory(ComboBoxTableCell.forTableColumn(new StringConverter<Grade>() {
@Override
public String toString(Grade grade) {
return grade.toString();
}
@Override
public Grade fromString(String s) {
return Grade.valueOf(s);
}
}, grades));
tbl.getColumns().add(col);
Student a = new Student();
a.grade = Grade.A;
a.name = "Mark";
tbl.setItems(FXCollections.observableArrayList(a));
root.getChildren().add(tbl);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
枚举
public enum Grade {
A (5),
B (4),
C (3),
D (2),
F (1);
int gradePoints;
Grade(int gradePoints) {
this.gradePoints = gradePoints;
}
public int getGradePoints() {
return gradePoints;
}
}
和学生 class:
public class Student {
String name; // name has the default value null
int age; // age has the default value 0
boolean isScienceMajor; // isScienceMajor has default value false
char gender; // gender has default value '\u0000'
Grade grade;
}
如何为 table 单元格定义值
您没有告诉系统如何找出单元格的值。
您需要在列上设置单元格值工厂。最简单的方法是让您的 Student class 使用和公开 JavaFX 属性,然后 set the cell value factory to a propertyValueFactory 命名与给定列关联的 属性。对于您的示例,这将是 "grade"
属性.
如何编辑单元格table
如果您希望 table 或特定列为 editable,您需要指定 the table is editable, and the columns are editable。您还需要在定义项目类型的 class 中公开适当的 setters 或 属性 方法。对于您的示例,这意味着在 Student
class 中为您希望能够关联的每个字段定义适当的属性 and/or getter 和 setter 函数与 table.
正如 fabian 在评论中所建议的那样,为了稳健性,最好让 StringConverter
的 ComboBoxTableCell
能够处理空值(如下面提供的示例代码所示) ).
用户如何编辑项目
要开始编辑单元格,用户需要双击单元格以将其从显示模式转换为编辑模式(然后将显示组合框,但没有下拉列表)。然后单击组合框将其下拉,然后从下拉列表中选择适当的等级,之后将保存该值并将单元格切换回读取模式。系统会知道。根据 属性 值定义,调用适当的 setter 将新选择的等级保存回基础项目的等级 属性。
示例应用程序
App.java
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class App extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
TableView<Student> tbl = new TableView<>();
tbl.setEditable(true);
TableColumn<Student, String> nameCol = new TableColumn<>("Name");
nameCol.setEditable(false);
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn<Student, Grade> gradeCol = new TableColumn<>("Grade");
gradeCol.setEditable(true);
ObservableList<Grade> grades = FXCollections.observableArrayList(Grade.values());
gradeCol.setCellFactory(
ComboBoxTableCell.forTableColumn(
new StringConverter<>() {
@Override
public String toString(Grade grade) {
return grade != null ? grade.toString() : null;
}
@Override
public Grade fromString(String s) {
return s != null ? Grade.valueOf(s) : null;
}
},
grades
)
);
gradeCol.setCellValueFactory(new PropertyValueFactory<>("grade"));
tbl.getColumns().addAll(nameCol, gradeCol);
Student aStudent = new Student(
"Mark", Grade.A
);
tbl.setItems(FXCollections.observableArrayList(aStudent));
root.getChildren().add(tbl);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
Student.java
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleObjectProperty;
public class Student {
private ReadOnlyStringWrapper name;
private ObjectProperty<Grade> grade;
public Student(String name, Grade grade) {
this.name = new ReadOnlyStringWrapper(name);
this.grade = new SimpleObjectProperty<>(grade);
}
public String getName() {
return name.get();
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
public Grade getGrade() {
return grade.get();
}
public ObjectProperty<Grade> gradeProperty() {
return grade;
}
public void setGrade(Grade grade) {
this.grade.set(grade);
}
}
成绩 class 与您问题中的定义没有变化。
无法弄清楚如何使用 ComboBox 将枚举列表添加到 table。目前代码无法编译,它在 StringConverter 的 grade.toString() 中失败。 以下是我正在使用的基本示例。最终我希望能够做三件事:
显示包含所有可用枚举的组合框
用当前成绩预填充它,如果有的话。
能够更改选择并使用新选择更新学生的对象。
有人可以帮忙吗?
public class App extends Application {
@Override
public void start(Stage stage) throws Exception {
try {
StackPane root = new StackPane();
TableView<Student> tbl = new TableView<>();
TableColumn<Student, Grade> col = new TableColumn<>("Grade");
ObservableList<Grade> grades = FXCollections.observableArrayList(Grade.values());
col.setCellFactory(ComboBoxTableCell.forTableColumn(new StringConverter<Grade>() {
@Override
public String toString(Grade grade) {
return grade.toString();
}
@Override
public Grade fromString(String s) {
return Grade.valueOf(s);
}
}, grades));
tbl.getColumns().add(col);
Student a = new Student();
a.grade = Grade.A;
a.name = "Mark";
tbl.setItems(FXCollections.observableArrayList(a));
root.getChildren().add(tbl);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
枚举
public enum Grade {
A (5),
B (4),
C (3),
D (2),
F (1);
int gradePoints;
Grade(int gradePoints) {
this.gradePoints = gradePoints;
}
public int getGradePoints() {
return gradePoints;
}
}
和学生 class:
public class Student {
String name; // name has the default value null
int age; // age has the default value 0
boolean isScienceMajor; // isScienceMajor has default value false
char gender; // gender has default value '\u0000'
Grade grade;
}
如何为 table 单元格定义值
您没有告诉系统如何找出单元格的值。
您需要在列上设置单元格值工厂。最简单的方法是让您的 Student class 使用和公开 JavaFX 属性,然后 set the cell value factory to a propertyValueFactory 命名与给定列关联的 属性。对于您的示例,这将是 "grade"
属性.
如何编辑单元格table
如果您希望 table 或特定列为 editable,您需要指定 the table is editable, and the columns are editable。您还需要在定义项目类型的 class 中公开适当的 setters 或 属性 方法。对于您的示例,这意味着在 Student
class 中为您希望能够关联的每个字段定义适当的属性 and/or getter 和 setter 函数与 table.
正如 fabian 在评论中所建议的那样,为了稳健性,最好让 StringConverter
的 ComboBoxTableCell
能够处理空值(如下面提供的示例代码所示) ).
用户如何编辑项目
要开始编辑单元格,用户需要双击单元格以将其从显示模式转换为编辑模式(然后将显示组合框,但没有下拉列表)。然后单击组合框将其下拉,然后从下拉列表中选择适当的等级,之后将保存该值并将单元格切换回读取模式。系统会知道。根据 属性 值定义,调用适当的 setter 将新选择的等级保存回基础项目的等级 属性。
示例应用程序
App.java
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class App extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
TableView<Student> tbl = new TableView<>();
tbl.setEditable(true);
TableColumn<Student, String> nameCol = new TableColumn<>("Name");
nameCol.setEditable(false);
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn<Student, Grade> gradeCol = new TableColumn<>("Grade");
gradeCol.setEditable(true);
ObservableList<Grade> grades = FXCollections.observableArrayList(Grade.values());
gradeCol.setCellFactory(
ComboBoxTableCell.forTableColumn(
new StringConverter<>() {
@Override
public String toString(Grade grade) {
return grade != null ? grade.toString() : null;
}
@Override
public Grade fromString(String s) {
return s != null ? Grade.valueOf(s) : null;
}
},
grades
)
);
gradeCol.setCellValueFactory(new PropertyValueFactory<>("grade"));
tbl.getColumns().addAll(nameCol, gradeCol);
Student aStudent = new Student(
"Mark", Grade.A
);
tbl.setItems(FXCollections.observableArrayList(aStudent));
root.getChildren().add(tbl);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
Student.java
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleObjectProperty;
public class Student {
private ReadOnlyStringWrapper name;
private ObjectProperty<Grade> grade;
public Student(String name, Grade grade) {
this.name = new ReadOnlyStringWrapper(name);
this.grade = new SimpleObjectProperty<>(grade);
}
public String getName() {
return name.get();
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
public Grade getGrade() {
return grade.get();
}
public ObjectProperty<Grade> gradeProperty() {
return grade;
}
public void setGrade(Grade grade) {
this.grade.set(grade);
}
}
成绩 class 与您问题中的定义没有变化。