Java 将组合框添加到TableColumn并绑定到行数据
我有一个简单的表单,如下所示: 这是MCVE代码。 Main.javaJava 将组合框添加到TableColumn并绑定到行数据,java,javafx,tableview,Java,Javafx,Tableview,我有一个简单的表单,如下所示: 这是MCVE代码。 Main.java public class Main extends Application { @Override public void start(Stage primaryStage) throws Exception{ Parent root = FXMLLoader.load(getClass().getResource("sample.fxml")); primaryStage
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
public class Controller {
@FXML
private TableView<TemplateColumn> tblColumns;
@FXML
private TableColumn<TemplateColumn, Integer> colColumnIndex;
@FXML
private TableColumn<TemplateColumn, String> colColumnName;
@FXML
private TableColumn<TemplateColumn, String> colMappedTo;
private Template sourceTemplate;
private Template destinationTemplate;
@FXML
private void initialize() {
createSampleData();
// Initialize the table
colColumnIndex.setCellValueFactory(new PropertyValueFactory<>("columnIndex"));
colColumnName.setCellValueFactory(new PropertyValueFactory<>("columnName"));
colMappedTo.setCellValueFactory(new PropertyValueFactory<>("destinationColumnIndex"));
tblColumns.setItems(sourceTemplate.getColumns());
ComboBox<TemplateColumn> cboMappedColumns = new ComboBox<>();
cboMappedColumns.setItems(destinationTemplate.getColumns());
}
private void createSampleData() {
destinationTemplate = new Template();
destinationTemplate.setTemplateName("Output");
destinationTemplate.setColumns(FXCollections.observableArrayList(
new TemplateColumn("Destination 0", 0, -1),
new TemplateColumn("Destination 1", 1, -1),
new TemplateColumn("Destination 2", 2, -1),
new TemplateColumn("Destination 3", 3, -1))
);
sourceTemplate = new Template();
sourceTemplate.setTemplateName("Input");
sourceTemplate.setColumns(FXCollections.observableArrayList(
new TemplateColumn("Source 0", 0, 3),
new TemplateColumn("Source 1", 1, 1),
new TemplateColumn("Source 2", 2, 0),
new TemplateColumn("Source 3", 3, 2))
);
sourceTemplate.setDestinationTemplate(destinationTemplate);
}
}
public class Template {
private final SimpleStringProperty templateName = new SimpleStringProperty("");
private final SimpleStringProperty destinationTemplateName = new SimpleStringProperty("");
private SimpleObjectProperty<Template> destinationTemplate = new SimpleObjectProperty<>();
// The list of TemplateColumns
private List<TemplateColumn> columns;
public Template() {
templateName.set("NEW");
}
public Template(ArrayList<TemplateColumn> columns) {
this.columns = columns;
}
public String getTemplateName() {
return templateName.get();
}
public SimpleStringProperty templateNameProperty() {
return templateName;
}
public void setTemplateName(String templateName) {
this.templateName.set(templateName);
}
public String getDestinationTemplateName() {
return destinationTemplateName.get();
}
public void setDestinationTemplateName(String destinationTemplateName) {
this.destinationTemplateName.set(destinationTemplateName);
}
public ObservableList<TemplateColumn> getColumns() {
return FXCollections.observableArrayList(columns);
}
public SimpleStringProperty destinationTemplateNameProperty() {
return destinationTemplateName;
}
public Template getDestinationTemplate() {
return destinationTemplate.get();
}
public SimpleObjectProperty<Template> destinationTemplateProperty() {
return destinationTemplate;
}
public void setDestinationTemplate(Template destinationTemplate) {
this.destinationTemplate.set(destinationTemplate);
}
public void setColumns(List<TemplateColumn> columns) {
this.columns = columns;
}
public TemplateColumn getReportColumn(int index) {
for (TemplateColumn col : columns) {
if (col.getColumnIndex() == index) return col;
}
return null;
}
@Override
public String toString() {
return templateName.get();
}
}
public class TemplateColumn {
private final SimpleStringProperty columnName = new SimpleStringProperty("");
private final SimpleIntegerProperty columnIndex = new SimpleIntegerProperty(0);
private final SimpleIntegerProperty destinationColumnIndex = new SimpleIntegerProperty(-1);
public TemplateColumn(String columnName, int columnIndex, int destinationColumnIndex) {
this.columnName.set(columnName);
this.columnIndex.set(columnIndex);
this.destinationColumnIndex.set(destinationColumnIndex);
}
public int getDestinationColumnIndex() {
return destinationColumnIndex.get();
}
public SimpleIntegerProperty destinationColumnIndexProperty() {
return destinationColumnIndex;
}
public void setDestinationColumnIndex(int destinationColumnIndex) {
this.destinationColumnIndex.set(destinationColumnIndex);
}
public String getColumnName() {
return columnName.get();
}
public SimpleStringProperty columnNameProperty() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName.set(columnName);
}
public int getColumnIndex() {
return columnIndex.get();
}
public SimpleIntegerProperty columnIndexProperty() {
return columnIndex;
}
public void setColumnIndex(int columnIndex) {
this.columnIndex.set(columnIndex);
}
@Override
public String toString() {
return columnName.get();
}
}
Controller.java
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
public class Controller {
@FXML
private TableView<TemplateColumn> tblColumns;
@FXML
private TableColumn<TemplateColumn, Integer> colColumnIndex;
@FXML
private TableColumn<TemplateColumn, String> colColumnName;
@FXML
private TableColumn<TemplateColumn, String> colMappedTo;
private Template sourceTemplate;
private Template destinationTemplate;
@FXML
private void initialize() {
createSampleData();
// Initialize the table
colColumnIndex.setCellValueFactory(new PropertyValueFactory<>("columnIndex"));
colColumnName.setCellValueFactory(new PropertyValueFactory<>("columnName"));
colMappedTo.setCellValueFactory(new PropertyValueFactory<>("destinationColumnIndex"));
tblColumns.setItems(sourceTemplate.getColumns());
ComboBox<TemplateColumn> cboMappedColumns = new ComboBox<>();
cboMappedColumns.setItems(destinationTemplate.getColumns());
}
private void createSampleData() {
destinationTemplate = new Template();
destinationTemplate.setTemplateName("Output");
destinationTemplate.setColumns(FXCollections.observableArrayList(
new TemplateColumn("Destination 0", 0, -1),
new TemplateColumn("Destination 1", 1, -1),
new TemplateColumn("Destination 2", 2, -1),
new TemplateColumn("Destination 3", 3, -1))
);
sourceTemplate = new Template();
sourceTemplate.setTemplateName("Input");
sourceTemplate.setColumns(FXCollections.observableArrayList(
new TemplateColumn("Source 0", 0, 3),
new TemplateColumn("Source 1", 1, 1),
new TemplateColumn("Source 2", 2, 0),
new TemplateColumn("Source 3", 3, 2))
);
sourceTemplate.setDestinationTemplate(destinationTemplate);
}
}
public class Template {
private final SimpleStringProperty templateName = new SimpleStringProperty("");
private final SimpleStringProperty destinationTemplateName = new SimpleStringProperty("");
private SimpleObjectProperty<Template> destinationTemplate = new SimpleObjectProperty<>();
// The list of TemplateColumns
private List<TemplateColumn> columns;
public Template() {
templateName.set("NEW");
}
public Template(ArrayList<TemplateColumn> columns) {
this.columns = columns;
}
public String getTemplateName() {
return templateName.get();
}
public SimpleStringProperty templateNameProperty() {
return templateName;
}
public void setTemplateName(String templateName) {
this.templateName.set(templateName);
}
public String getDestinationTemplateName() {
return destinationTemplateName.get();
}
public void setDestinationTemplateName(String destinationTemplateName) {
this.destinationTemplateName.set(destinationTemplateName);
}
public ObservableList<TemplateColumn> getColumns() {
return FXCollections.observableArrayList(columns);
}
public SimpleStringProperty destinationTemplateNameProperty() {
return destinationTemplateName;
}
public Template getDestinationTemplate() {
return destinationTemplate.get();
}
public SimpleObjectProperty<Template> destinationTemplateProperty() {
return destinationTemplate;
}
public void setDestinationTemplate(Template destinationTemplate) {
this.destinationTemplate.set(destinationTemplate);
}
public void setColumns(List<TemplateColumn> columns) {
this.columns = columns;
}
public TemplateColumn getReportColumn(int index) {
for (TemplateColumn col : columns) {
if (col.getColumnIndex() == index) return col;
}
return null;
}
@Override
public String toString() {
return templateName.get();
}
}
public class TemplateColumn {
private final SimpleStringProperty columnName = new SimpleStringProperty("");
private final SimpleIntegerProperty columnIndex = new SimpleIntegerProperty(0);
private final SimpleIntegerProperty destinationColumnIndex = new SimpleIntegerProperty(-1);
public TemplateColumn(String columnName, int columnIndex, int destinationColumnIndex) {
this.columnName.set(columnName);
this.columnIndex.set(columnIndex);
this.destinationColumnIndex.set(destinationColumnIndex);
}
public int getDestinationColumnIndex() {
return destinationColumnIndex.get();
}
public SimpleIntegerProperty destinationColumnIndexProperty() {
return destinationColumnIndex;
}
public void setDestinationColumnIndex(int destinationColumnIndex) {
this.destinationColumnIndex.set(destinationColumnIndex);
}
public String getColumnName() {
return columnName.get();
}
public SimpleStringProperty columnNameProperty() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName.set(columnName);
}
public int getColumnIndex() {
return columnIndex.get();
}
public SimpleIntegerProperty columnIndexProperty() {
return columnIndex;
}
public void setColumnIndex(int columnIndex) {
this.columnIndex.set(columnIndex);
}
@Override
public String toString() {
return columnName.get();
}
}
问题
基本上,我需要的是cboMappedColumns
组合框,它将显示在映射到表中每一行的列的中,并将其值绑定(双向)到TemplateColumn
,其columnIndex
与行的源TemplateColumn
的destinationColumnIndex
匹配
因此,它不是在第一行显示“3”,而是一个选择了值“Destination 3”的组合框
注意:这是我第三次尝试发布有效问题;如果我还缺什么,请告诉我。谢谢你的帮助 setCellFactory
用于包含组合框的列
:
- 创建类型的新组合框,并将其value属性双向绑定到类中所需的属性
- 将创建的组合框
设置为行的图形
我希望下面的例子能帮助你解决问题
控制器:
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
public class FXMLDocumentController implements Initializable {
@FXML
private TableView<Employee> table;
@FXML
private TableColumn<Employee, String> nameColumn;
@FXML
private TableColumn<Employee, CompanyType> companyTypeColumn;
@Override
public void initialize(URL url, ResourceBundle rb) {
nameColumn.setCellValueFactory((param) -> {
return new SimpleStringProperty(param.getValue().getName());
});
companyTypeColumn.setCellValueFactory((param) -> {
return param.getValue().companyTypeProperty();
});
companyTypeColumn.setCellFactory((column) -> {
return new TableCell<Employee, CompanyType>() {
@Override
protected void updateItem(CompanyType item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
ComboBox<CompanyType> comboBox = new ComboBox<>(FXCollections.observableArrayList(CompanyType.values()));
Employee employee = (Employee) getTableRow().getItem();
comboBox.valueProperty().bindBidirectional(employee.companyTypeProperty());
setGraphic(comboBox);
} else {
setText(null);
setGraphic(null);
}
}
};
});
table.getItems().add(new Employee("Foo", CompanyType.PRIVATE));
table.getItems().add(new Employee("Bar", CompanyType.PUBLIC));
table.getItems().add(new Employee("John", CompanyType.PUBLIC));
}
}
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
public class Employee {
private String name;
public Employee(String name, CompanyType companyType) {
this.name = name;
this.setCompanyType(companyType);
}
private final ObjectProperty<CompanyType> companyType = new SimpleObjectProperty<>();
public CompanyType getCompanyType() {
return companyType.get();
}
public void setCompanyType(CompanyType value) {
companyType.set(value);
}
public ObjectProperty companyTypeProperty() {
return companyType;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Employee{" + "name=" + name + ", companyType=" + companyType + '}';
}
}
public enum CompanyType {
PRIVATE, PUBLIC;
}
和往常一样,您需要一个使用组合的单元格,并设置一个回调,将其创建为列的cellFactory(您可以使用一个ComboBoxTableCell)——因此不太了解问题所在,没有什么特别的。。。至于重复发布同一个问题:最好不要(每个人都需要重新阅读并与之前的问题建立联系)-而是根据需要编辑一个问题并添加详细信息:)谢谢你,@kleopatra,但是我如何根据组合框的一个属性将组合框的值绑定到
TemplateColumn
?与中一样,如何搜索组合框中的所有项目,并找到具有正确columnIndex
属性的项目?我想这是我的主要问题。。不理解:为什么要“绑定”任何内容(顺便说一句,代码中没有显示的内容)-comboCell将像任何其他单元格一样显示和编辑其内容的数据。组合框选择需要与行数据的destinationColumnIndex
属性绑定。因此,更改组合框值本质上应该执行rowData.setDestinationColumnIndex(cboDestinationColumn.getValue().getColumnIndex())
。反之亦然:每行的组合框最初应设置为组合框中的TemplateColumn
,该组合框的columnIndex
与行数据的destinationColumnIndex
属性值匹配。您的代码有几个问题(没有特定顺序):a)您在每次调用updateItem时都重新创建一个新组合b)单元格不能更改脚下的数据(如绑定所做的那样),相反,设置必须使用编辑机制c)您的示例与OPs设置不同,因为组合项的类型与列类型相同-这是正确的做法,但不能解决OPs问题;)谢谢你的反馈。我将尝试相应地编辑我的答案。