Java 将组合框添加到TableColumn并绑定到行数据

Java 将组合框添加到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

我有一个简单的表单,如下所示:

这是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.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问题;)谢谢你的反馈。我将尝试相应地编辑我的答案。