[英]ComboBox in a tableview cell in JavaFX
我正在尝试向我的Table View
添加一个Combo Box
:
基本上我有一个名为 TableViewTest 的类,它存储一个名称和一个描述,我可以在Table View
显示这些名称和描述而无需打扰,但我想要做的是添加第三列,每个单元格都有一个Combo Box
以便用户可以为每个人从多个选项中选择一个。
到目前为止,我已经创建了一个带有一些值的String
类型的ObservableList
并将它们添加到ComboBox
对象中。 有谁知道我可以将这个Combo Box
添加到表格中的方法吗?
还要记住,这段代码非常粗糙,我只是想让一些东西工作,我将在以后重构代码。
ObservableList<TableViewTest> products = FXCollections.observableArrayList();
for(int i = 0; i < b.length; i++){
// random String values
products.add(new TableViewTest(b[i], a[i]));
}
ObservableList<String> options = FXCollections.observableArrayList(
"1",
"2",
"3"
);
final ComboBox comboBox = new ComboBox(options);
TableColumn<TableViewTest, String> nameColumn = new TableColumn<> ("Name");
nameColumn.setMinWidth(200);
nameColumn.setCellValueFactory(new PropertyValueFactory<TableViewTest, String>("name"));
//price Column
//Stock Column
TableColumn<TableViewTest, String> StockColumn = new TableColumn<> ("Stock");
StockColumn.setMinWidth(150);
StockColumn.setCellValueFactory(new PropertyValueFactory<TableViewTest, String>("description"));
TableColumn<Object,ComboBox> PriceColumn;
PriceColumn = new TableColumn<>("Source");
PriceColumn.setMinWidth(150);
//PriceColumn.setCellValueFactory(new PropertyValueFactory<>
//(options));
//PriceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(new
//DefaultStringConverter(), options));
//PriceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(
//comboBox));
TableView<TableViewTest> table = new TableView<>();
table.setItems(products);
table.getColumns().addAll(nameColumn, StockColumn, PriceColumn);
表格列的类型始终是第一个类型参数的每行中项目的类型(即与您用于表格视图的类型相同),以及每个单元格的(当前)值的类型第二个参数的列。 因此,如果您的表视图具有TableViewTest
类型,并且您的组合框正在选择String
s,则您应该:
TableColumn<TableViewTest, String> priceColumn ;
单元格值工厂仍应映射到TableViewTest
类中的属性,即假设您有:
public class TableViewTest {
// ...
public StringProperty priceProperty() {
// ...
}
// ...
}
那么你可以这样做:
priceColumn.setCellValueFactory(new PropertyValueFactory<>("price"));
或(更好):
priceColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty());
然后你可以这样做:
priceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(options));
这是一个 SSCCE:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
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.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TableWithComboBoxExample extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Contact> contactTable = new TableView<>();
contactTable.setEditable(true);
TableColumn<Contact, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
contactTable.getColumns().add(nameCol);
TableColumn<Contact, String> categoryCol = new TableColumn<>("Category");
categoryCol.setCellValueFactory(cellData -> cellData.getValue().categoryProperty());
categoryCol.setCellFactory(ComboBoxTableCell.forTableColumn("Friends", "Family", "Work Contacts"));
contactTable.getColumns().add(categoryCol);
contactTable.getItems().addAll(
new Contact("Bill Gates", "Work Contacts"),
new Contact("Barack Obama", "Friends"),
new Contact("Tim Cook", "Work Contacts")
);
Scene scene = new Scene(new BorderPane(contactTable), 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Contact {
private final StringProperty name = new SimpleStringProperty();
private final StringProperty category = new SimpleStringProperty();
public Contact(String name, String category) {
setName(name);
setCategory(category);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final StringProperty categoryProperty() {
return this.category;
}
public final String getCategory() {
return this.categoryProperty().get();
}
public final void setCategory(final String category) {
this.categoryProperty().set(category);
}
}
public static void main(String[] args) {
launch(args);
}
}
James_D 的答案效果很好,但需要用户单击该项目才能看到ComboBox
。 如果您想在一列中包含ComboBox
es,始终显示,您必须使用自定义cellFactory
:
public class TableViewTest {
...
private final StringProperty option = new SimpleStringProperty();
public String getOption() {
return option.get();
}
public void setOption(String value) {
option.set(value);
}
public StringProperty optionProperty() {
return option;
}
}
TableColumn<TableViewTest, StringProperty> column = new TableColumn<>("option");
column.setCellValueFactory(i -> {
final StringProperty value = i.getValue().optionProperty();
// binding to constant value
return Bindings.createObjectBinding(() -> value);
});
column.setCellFactory(col -> {
TableCell<TableViewTest, StringProperty> c = new TableCell<>();
final ComboBox<String> comboBox = new ComboBox<>(options);
c.itemProperty().addListener((observable, oldValue, newValue) -> {
if (oldValue != null) {
comboBox.valueProperty().unbindBidirectional(oldValue);
}
if (newValue != null) {
comboBox.valueProperty().bindBidirectional(newValue);
}
});
c.graphicProperty().bind(Bindings.when(c.emptyProperty()).then((Node) null).otherwise(comboBox));
return c;
});
所以我需要做基本相同的事情,在 TableView 的列中显示一个动态组合框。 我确信这些其他解决方案是灵活的,但它们似乎不必要地先进。
我找到的最简单的解决方案是将 ComboBox 属性添加到我的项目类(在您的情况下TableViewTest
),为其创建一个公共 getter 并将其视为标准SimpleXProperty
。 然后显示它,简单地将组合框列的单元格值工厂设置为PropertyValueFactory
并输入您的 getter 的名称。
以下代码是 groovy,因为它是我实现项目的语言,但对于 Java 应该几乎相同:
请注意, ComboBoxItem
可以是您要在组合框中列出的任何类。
在我扩展TableView
自定义表类中:
class CustomTable extends TableView<CustomTableItem> {
CustomTable() {
TableColumn columnA = new TableColumn("Column A")
columnA.setCellValueFactory(new PropertyValueFactory<>("propertyA"))
TableColumn<CustomTableItem, ComboBoxItem> comboBoxColumn = new TableColumn<CustomTableItem, ComboBoxItem>("ComboBox Column")
comboBoxColumn.setCellValueFactory(new PropertyValueFactory<>("comboBoxProperty"))
getColumns().setAll(columnA, comboBoxColumn)
}
}
自定义表项
class CustomTableItem {
private SimpleStringProperty propertyA = new SimpleStringProperty()
private ComboBox comboBox = new ComboBox()
CustomTableItem(String someValue, List<ComboBoxItem> items) {
propertA.setValue(someValue)
comboBox.getItems().setAll(items)
comboBox.setConverter(new CustomStringConverter()) // Optional
}
String getPropertyA() {
return propertyA.value
}
ComboBox getComboBoxProperty() {
return comboBox
}
}
最后,作为奖励,使用StringConverter
来控制如何在组合框中显示对象
@CompileStatic
private static class CustomStringConverter extends StringConverter<ComboBoxItem> {
@Override
String toString(ComboBoxItem object) {
return object?.toString() // How the ComboBoxItem will be displayed in the combo box
}
@Override
ComboBoxItem fromString(String string) {
return null // Not used
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.