没有对象的 TableView 中的组合框 - JavaFX

Posted

技术标签:

【中文标题】没有对象的 TableView 中的组合框 - JavaFX【英文标题】:ComboBox in TableView without Object - JavaFX 【发布时间】:2021-10-04 05:46:25 【问题描述】:

我已经在互联网上搜索了一段时间关于用ComboBox 填充TableView 的单元格的解释,但它们每个都使用以下行:

    TableView<SomeObject> tableView = new TableView<>();
    TableColumn<SomeObject, String> column = new TableColumn<>("property");
    ObservableList<String> list = FXCollections.observableArrayList("option1", "option2", "option3");
    column.setCellValueFactory(new PropertyValueFactory<>("property"));
    column.setCellFactory(ComboBoxTableCell.forTableColumn(list);
    tableView.getColumns().add(column);

...在另一个类中定义了SomeObject

关键是,我正在构建一个 GUI,我无法定义 Object 来填充任何 TableView(因为我无法预测我的表将包含的列数)。我所知道的是我的TableView 将充满String,并且前两列将始终具有相同的标题(“N°”和“Truth”)。没有其他的。所以我不能使用上面的代码,因为我没有任何"property" 可以填写。

这是我如何填写我的TableView,没有ComboBox,(它工作正常),我的数据被称为rawData,它是一个Partionner(下面的代码):

ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
for(int i = 1; i < rawData.size(); i++)
    // Begin at i = 1 because the first raw (i = 0) is the names of the columns.
    data.add(FXCollections.observableArrayList(rawData.get(i)));

tableView.setItems(data);

for(int i = 0; rawData.get(0).size(); i++)
    final int cuurentColumn = i;
    TableColumn<ObservableList<String>, String> column = new TableColumn<>((String) rawData.get(0).get(i)); // Here are the columns titles.
    column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(currentColumn)));
    column.setStyle("-fx-alignment: CENTER");
    tableView.getColumns().add(column);

Partionner 在哪里:

public final class Partionner<T> extends AbstractList<List<T>>
    private final List<T> list;
    private final int chunkSize;

    public Partionner(List<T> list, int chunkSize)
        this.list = list;
        this.chunkSize = chunkSize;
    

    public static <T> Partitionner<T> ofSize(List<T> list, int chunkSize)
        return new Partionner<>(list, chunkSize);
    

    @Override
    public List<T> get(int index)
        int start = index * chunkSize;
        int end = Math.min(start + chunkSize, list.size());
        if(start > end)
            throw new IndexOutOfBoundsException("OOB Partitionner");
        
        return new ArrayList<>(list.subList(start, end));
    

    public int size()
        return (int) Math.ceil((double) list.size() / (double) chunkSize);
    
// You can create a Partionner with :
Partitionner partitionner = Partitionner.ofSize(arrayList, length);
// Where arraylist is an ArrayList<String> and length it's size

从实际上来自 CSV 的所有这些数据中,我想为第二列“Truth”的每个单元格使用一个组合框。我想到了类似的东西:

ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
for(int i = 1; i < rawData.size(); i++)
    // Begin at i = 1 because the first raw (i = 0) is the names of the columns.
    data.add(FXCollections.observableArrayList(rawData.get(i)));

tableView.setItems(data);

for(int i = 0; i < rawData.get(0).size(); i++)
    final int currentColumn = i;
    if(i == 1)
        // So it's here I'm completly disabled to fill this code :/
        // Begin of bullshit
        TableColumn<ObservableList<String>, String> column = new TableColumn<>((String) rawData.get(0).get(i));
        ObservableList<String> possibleTruth = FXCollections.obervableArrayList("1", "2", "3");
        final ComboBox<String> comboBox = new ComboBox<>(possibleTruth);
        column.setCellValueFactory(......);
        column.setCellFactory(......);
        tableView.getColumns.add(col);
        // End of bullshit

     else 
        TableColumn<ObservableList<String>, String> column = new TableColumn<>((String) rawData.get(0).get(i));
        column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(currentColumn)));
        column.setStyle("-fx-alignment: CENTER");
        tableView.getColumns().add(column);
    

有什么想法可以填写我的代码吗?如果您的解决方案有效,请随时离开您的贝宝哈哈 (jk) :)

----------- 这是一个最小的可复制示例 -----------

类主:

public class Main extends Application 

    @Override
    public void start(Stage primaryStage) throws Exception
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setResizable(false);
        Scene scene = new Scene(root, 1280, 720);
        primaryStage.setScene(scene);
        primaryStage.show();
    


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

类控制器:

public class Controller 
    @FXML public TableView tableView;
    public ArrayList<String> inputData;
    public Partitionner rawData;

    public void initialize()
        inputData = new ArrayList<>();
        inputData.add("N°");
        inputData.add("Truth");
        inputData.add("Col A");
        inputData.add("Col B");
        inputData.add("1");
        inputData.add("t1");
        inputData.add("valA1");
        inputData.add("valB1");
        inputData.add("2");
        inputData.add("t2");
        inputData.add("valA2");
        inputData.add("valB2");
        inputData.add("3");
        inputData.add("t3");
        inputData.add("valA3");
        inputData.add("valB3");
        rawData = Partitionner.ofSize(inputData, 4);
        System.out.println(rawData);
    

    public void populateTableView ()
        ObservableList<ObservableList<String>> data = FXCollections.observableArrayList();
        for(int i = 1; i < rawData.size(); i++)
            // Begin at i = 1 because the first raw (i = 0) is the names of the columns.
            data.add(FXCollections.observableArrayList(rawData.get(i)));
        
        tableView.setItems(data);

        for(int i = 0; i < rawData.get(0).size(); i++)
            final int currentColumn = i;
            if(i == 1)
                // Trying to fill the "Truth" column with a combobox in each cell containing t1, t2 and t3.
                TableColumn<ObservableList<String>, String> column = new TableColumn<>((String) rawData.get(0).get(i));
                ObservableList<String> possibleTruth = FXCollections.observableArrayList("t1", "t2", "t3");
              column.setCellFactory(ComboBoxTableCell.forTableColumn(possibleTruth));
                tableView.getColumns().add(column);

             else 
                TableColumn<ObservableList<String>, String> column = new TableColumn<>((String) rawData.get(0).get(i));
                column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(currentColumn)));
                column.setStyle("-fx-alignment: CENTER");
                tableView.getColumns().add(column);
            
        
    

sample.fxml 文件:

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="752.0" prefWidth="1162.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <Button layoutX="140.0" layoutY="683.0" mnemonicParsing="false" onAction="#populateTableView" prefHeight="25.0" prefWidth="161.0" text="Fill Data" />
      <TableView fx:id="tableView" layoutX="43.0" layoutY="39.0" prefHeight="585.0" prefWidth="1073.0" />
   </children>
</AnchorPane>

别忘了添加上面的Partitionner 类。

【问题讨论】:

您忘记为组合列设置 cellValueFactory,请参阅 James 的回答并将其应用于 字母 顺便说一句:这不是最小的(简单列表中的硬编码数据可以,不需要任何专门的 impl,比如 Partitionner) 您好,谢谢您的回答。添加 column.setCellValueFactory(param -> new ReadOnlyObjectWrapper(param.getValue().get(currentColumn)));仅在第一个单元格中显示“t1”​​,在第二个单元格中显示“t2”,在第三个中显示“t3”,而不是添加 ComboBox。知道为什么吗? 【参考方案1】:

只需组合您已有的部分即可。以下不是你想要的吗?

for(int i = 0; rawData.get(0).size(); i++)
    final int currentColumn = i;
    TableColumn<ObservableList<String>, String> column = new TableColumn<>((String) rawData.get(0).get(i);
    column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(currentColumn)));
    column.setStyle("-fx-alignment: CENTER");
    tableView.getColumns().add(column);

    if(i == 1)
        ObservableList<String> possibleTruth = FXCollections.obervableArrayList("1", "2", "3");
        column.setCellFactory(ComboBoxTableCell.forTableColumn(possibleTruth));
     

【讨论】:

您好,感谢您的回答。如果我按照你说的做,我将在同一列中的 rawData 中的字符串 int 的第二列(Truth),而不是带有选项 1、2、3 的 ComboBox。这正是我不明白的:/ @Pierre-Olivier 我不明白你的评论。您可能需要创建一个minimal reproducible example 并将其发布在您的问题中以演示问题。 在这里。希望它能帮助你回答我。正如您将在这段代码中看到的那样,“Truth”列是空的。

以上是关于没有对象的 TableView 中的组合框 - JavaFX的主要内容,如果未能解决你的问题,请参考以下文章

如何根据javafx中的Action为同一个tableview提供一个Contextmenu?

组合框中的Javascript存储对象

Qt C++根据组合框中的选择创建一个对象

如何动态更改 C# 组合框或文本框中的自动完成条目?

如何将 ARGB 值绑定到组合框项中的矩形填充属性?

用于打开报告的组合框 - 无法选择组合框中的项目