【问题标题】:JavaFX Nested TableView SpacingJavaFX 嵌套 TableView 间距
【发布时间】:2021-06-30 10:18:45
【问题描述】:

所以我尝试使用 JavaFX 创建一个嵌套表,但遇到了间距问题。我正在使用标准方法来创建主表,那里没什么特别的。但是嵌套表:我正在按照我在此链接https://edencoding.com/tableview-customization-cellfactory/ 找到的指南进行操作,除了插入嵌套表时添加到行中的空间之外,一切都按应有的方式工作。我希望主表的行与整个嵌套表的高度相同,但它比这大得多,我似乎无法调整它的大小。

我尝试了以下方法:

  1. 在 cell.itemProperty 监听器中,我设置了单元格 maxHeight。
  2. 我设置了嵌套 TableView 的最大高度。
  3. 在底部的第二个链接中,您可以看到我使用 ChoiceBox 而不是 TableView 时的图片。这确实使行的大小正确(它适合选择框)。
  4. 删除了 ConstrainedResize 政策
  5. 在从 cell.itemProperty 侦听器返回单元格之前将单元格的最大高度设置为固定值。
  6. 在从 cell.itemProperty 侦听器返回单元之前调用 cell.resize(n,n)。

这里是创建表的代码。此方法在控制器类中。 BlendedWordRecall 类是一个非常简单的 POJO,BlendClass 是一个接口,但同样,非常基本的 getter 和 setter 没有什么花哨的。

private TableView getBlendingTableView(List<BlendedWordRecall> recalls) {
        ObservableList<BlendedWordRecall> data = FXCollections.observableArrayList();
        data.addAll(recalls);
        
        TableView<BlendedWordRecall> table = new TableView<BlendedWordRecall>();
        table.setMinWidth(1250);
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        TableColumn<BlendedWordRecall, String> wordCol = new TableColumn<BlendedWordRecall, String>("Word");
        wordCol.setMinWidth(150);
        wordCol.setCellValueFactory(cellData -> {
            return new SimpleStringProperty(cellData.getValue().getWord());
        });
        
        TableColumn<BlendedWordRecall, String> recallDateCol = new TableColumn<BlendedWordRecall, String>("Recall Date");
        recallDateCol.setMinWidth(230);
        recallDateCol.setCellValueFactory(cellData -> {
            LocalDateTime ldt = LocalDateTime.ofInstant(cellData.getValue().getDateOfRecall().toInstant(),ZoneId.systemDefault());
            return new SimpleStringProperty(ldt.format(dateTimeFormat));
        });
        
        TableColumn<BlendedWordRecall, String> correctCol = new TableColumn<BlendedWordRecall, String>("Correct?");
        correctCol.setMinWidth(230);
        correctCol.setCellValueFactory(cellData -> {
            String booleanString = cellData.getValue().isWasCorrect() == true ? "Correct" : "Incorrect";
            return new SimpleStringProperty(booleanString);
        });
        correctCol.setCellFactory(column -> {
            return new TableCell<BlendedWordRecall, String>() {
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
        
                    if (item == null || empty) {
                        setText(null);
                        setStyle("");
                    } else {
                        if (item.equals("Correct")) {
                            setText("Correct");
                            setStyle("  -fx-font-size: 14px;\r\n" + 
                                            "   -fx-font-family: \"Comic Sans MS\";\r\n" + 
                                            "   -fx-font-weight: bolder;\r\n" + 
                                            "    -fx-text-fill: #37ff00;");
                        } else {
                            setText("Incorrect");
                            setStyle("  -fx-font-size: 14px;\r\n" + 
                                            "   -fx-font-family: \"Comic Sans MS\";\r\n" + 
                                            "   -fx-font-weight: bolder;\r\n" + 
                                            "    -fx-text-fill: #E60000;");
                        }
                    }
                }
            };
        });
        
        TableColumn<BlendedWordRecall, String> sightCol = new TableColumn<BlendedWordRecall, String>("Sight Read?");
        sightCol.setMinWidth(150);
        sightCol.setCellValueFactory(cellData -> {
            String sightString = cellData.getValue().isWasSightRead() == true ? "True" : "False";
            return new SimpleStringProperty(sightString);
        });
        
        TableColumn<BlendedWordRecall, String> recallTimeCol = new TableColumn<BlendedWordRecall, String>("Recall Time");
        recallTimeCol.setMinWidth(150);
        recallTimeCol.setCellValueFactory(cellData -> {
            String timeString = String.format("%.2f", cellData.getValue().getRecallDuration())+" Sec";
            return new SimpleStringProperty(timeString);
        });

        TableColumn<BlendedWordRecall, String> blendsCol = new TableColumn<BlendedWordRecall, String>("Blends");
        blendsCol.setMinWidth(300);
        blendsCol.setCellValueFactory(cellData -> {
            return new SimpleStringProperty("yes");// Set just so the cell.itemProperty will fire all the time
        });
         blendsCol.setCellFactory(col -> {
            TableCell<BlendedWordRecall, String> cell = new TableCell<>();
            
            cell.itemProperty().addListener((obs, old, newVal) -> {
                if (newVal != null) {
                    //////////////////////////////// Create nested table //////////////////////////////////////
                    ObservableList<BlendClass> blendList = FXCollections.observableArrayList();
                    SingleLetterBlendRecall slbOne = new SingleLetterBlendRecall("a / A", "A" , "b / B", "B");
                    SingleLetterBlendRecall slbTwo = new SingleLetterBlendRecall("b / B", "B" , "c / C", "C");
                    blendList.addAll(slbOne,slbTwo);
                    TableView<BlendClass> blendTable = new TableView<BlendClass>();
                    blendTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
                    TableColumn<BlendClass, String> firstCol = new TableColumn<BlendClass, String>("First Sound");
                    firstCol.setMinWidth(150);
                    firstCol.setCellValueFactory(cellData -> {
                        return new SimpleStringProperty(cellData.getValue().getFirstSoundName());
                    });
                    
                    TableColumn<BlendClass, String> secondCol = new TableColumn<BlendClass, String>("Second Sound");
                    secondCol.setMinWidth(150);
                    secondCol.setCellValueFactory(cellData -> {
                        return new SimpleStringProperty(cellData.getValue().getSecondSoundName());
                    });
                    blendTable.getColumns().addAll(firstCol, secondCol);
                    blendTable.setItems(blendList);
                    blendTable.setMaxHeight(40 + (30*blendList.size()));
                    ///////////////////////////////////////////////////////////////////////////////////
                    cell.graphicProperty().bind(Bindings.when(cell.emptyProperty()).then((Node) null).otherwise(blendTable));
            }
        });
        return cell;
    });
        table.getColumns().addAll(wordCol, recallDateCol, correctCol, sightCol, recallTimeCol, blendsCol);
        table.setItems(data);
        
    return table;
}   

Table made with current code

Table made using a choice box instead of a nested table

Table made without resizing the nested table

基于第一张图片中的表格与第三张图片中的表格具有相同的行大小这一事实,我很确定这是一个时间问题。就像在我调整表格大小或其他东西之前布局正在发生一样。任何关于从这里去哪里的想法都会很棒,谢谢大家。

【问题讨论】:

标签: java javafx layout tableview nested-table


【解决方案1】:

我终于想通了。希望它会帮助遇到同样问题的其他人。在构建嵌套表时,我最初只是设置了最大高度,这使得嵌套表的大小正确,但包含它的单元格是嵌套表的原始大小,然后我设置了它的最大高度。显然,如果您设置嵌套表的最大、最小和首选高度,那么它的行为正确,因为包含嵌套表的单元格将根据嵌套表的大小调整大小。这是一张供参考的图片。

Correct output

这是更新后的代码,只更改了两行:

private TableView getBlendingTableView(List<BlendedWordRecall> recalls) {
        ObservableList<BlendedWordRecall> data = FXCollections.observableArrayList();
        data.addAll(recalls);
        
        TableView<BlendedWordRecall> table = new TableView<BlendedWordRecall>();
        table.setMinWidth(1250);
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        TableColumn<BlendedWordRecall, String> wordCol = new TableColumn<BlendedWordRecall, String>("Word");
        wordCol.setMinWidth(150);
        wordCol.setCellValueFactory(cellData -> {
            return new SimpleStringProperty(cellData.getValue().getWord());
        });
        
        TableColumn<BlendedWordRecall, String> recallDateCol = new TableColumn<BlendedWordRecall, String>("Recall Date");
        recallDateCol.setMinWidth(230);
        recallDateCol.setCellValueFactory(cellData -> {
            LocalDateTime ldt = LocalDateTime.ofInstant(cellData.getValue().getDateOfRecall().toInstant(),ZoneId.systemDefault());
            return new SimpleStringProperty(ldt.format(dateTimeFormat));
        });
        
        TableColumn<BlendedWordRecall, String> correctCol = new TableColumn<BlendedWordRecall, String>("Correct?");
        correctCol.setMinWidth(230);
        correctCol.setCellValueFactory(cellData -> {
            String booleanString = cellData.getValue().isWasCorrect() == true ? "Correct" : "Incorrect";
            return new SimpleStringProperty(booleanString);
        });
        correctCol.setCellFactory(column -> {
            return new TableCell<BlendedWordRecall, String>() {
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
        
                    if (item == null || empty) {
                        setText(null);
                        setStyle("");
                    } else {
                        if (item.equals("Correct")) {
                            setText("Correct");
                            setStyle("  -fx-font-size: 14px;\r\n" + 
                                            "   -fx-font-family: \"Comic Sans MS\";\r\n" + 
                                            "   -fx-font-weight: bolder;\r\n" + 
                                            "    -fx-text-fill: #37ff00;");
                        } else {
                            setText("Incorrect");
                            setStyle("  -fx-font-size: 14px;\r\n" + 
                                            "   -fx-font-family: \"Comic Sans MS\";\r\n" + 
                                            "   -fx-font-weight: bolder;\r\n" + 
                                            "    -fx-text-fill: #E60000;");
                        }
                    }
                }
            };
        });
        
        TableColumn<BlendedWordRecall, String> sightCol = new TableColumn<BlendedWordRecall, String>("Sight Read?");
        sightCol.setMinWidth(150);
        sightCol.setCellValueFactory(cellData -> {
            String sightString = cellData.getValue().isWasSightRead() == true ? "True" : "False";
            return new SimpleStringProperty(sightString);
        });
        
        TableColumn<BlendedWordRecall, String> recallTimeCol = new TableColumn<BlendedWordRecall, String>("Recall Time");
        recallTimeCol.setMinWidth(150);
        recallTimeCol.setCellValueFactory(cellData -> {
            String timeString = String.format("%.2f", cellData.getValue().getRecallDuration())+" Sec";
            return new SimpleStringProperty(timeString);
        });

        TableColumn<BlendedWordRecall, String> blendsCol = new TableColumn<BlendedWordRecall, String>("Blends");
        blendsCol.setMinWidth(300);
       
        blendsCol.setCellValueFactory(cellData -> {
            return new SimpleStringProperty("yes");// Set just so the cell.itemProperty will fire all the time
        });
         blendsCol.setCellFactory(col -> {
             
            TableCell<BlendedWordRecall, String> cell = new TableCell<>();
            
            cell.itemProperty().addListener((obs, old, newVal) -> {
                if (newVal != null) {
                    //////////////////////////////// Create nested table //////////////////////////////////////
                    ObservableList<BlendClass> blendList = FXCollections.observableArrayList();
                    SingleLetterBlendRecall slbOne = new SingleLetterBlendRecall("a / A", "A" , "b / B", "B");
                    SingleLetterBlendRecall slbTwo = new SingleLetterBlendRecall("b / B", "B" , "c / C", "C");
                    blendList.addAll(slbOne,slbTwo);
                    TableView<BlendClass> blendTable = new TableView<BlendClass>();
                    
                    blendTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
                    TableColumn<BlendClass, String> firstCol = new TableColumn<BlendClass, String>("First Sound");
                    firstCol.setMinWidth(150);
                    firstCol.setCellValueFactory(cellData -> {
                        return new SimpleStringProperty(cellData.getValue().getFirstSoundName());
                    });
                    
                    TableColumn<BlendClass, String> secondCol = new TableColumn<BlendClass, String>("Second Sound");
                    secondCol.setMinWidth(150);
                    secondCol.setCellValueFactory(cellData -> {
                        return new SimpleStringProperty(cellData.getValue().getSecondSoundName());
                    });
                    blendTable.getColumns().addAll(firstCol, secondCol);
                    blendTable.setItems(blendList);
                    blendTable.setMaxHeight(40 + (30*blendList.size()));
                    blendTable.setMinHeight(40 + (30*blendList.size()));
                    blendTable.setPrefHeight(40 + (30*blendList.size()));
                    ///////////////////////////////////////////////////////////////////////////////////
                    cell.graphicProperty().bind(Bindings.when(cell.emptyProperty()).then((Node) null).otherwise(blendTable));
                   
            }
        });
        return cell;
    });
        
        table.getColumns().addAll(wordCol, recallDateCol, correctCol, sightCol, recallTimeCol, blendsCol);
        table.setItems(data);
        
        
    return table;
}   

【讨论】:

    猜你喜欢
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 2021-05-27
    • 1970-01-01
    相关资源
    最近更新 更多