首页 > 解决方案 > 我可以在构建它的 CellValueFactory 时检查 TableCell 的内容是否会溢出

问题描述

我有一个 JavaFX 表列,我想显示一个逗号分隔的字符串列表,除非文本不适合单元格的当前边界,此时它将显示,例如,“ Foo and 3 others...”或“ 3 Bars” ,即反映列表中元素的数量

有没有办法在为表格列构建 CellValueFactory 时检查文本是否会超出单元格,以便我可以在这两种行为之间切换?

标签: javajavafxtableview

解决方案


Labeled您可以为 s等控件指定溢出样式TableCell

Overrun 样式ELLIPSIS将根据需要自动添加这些省略号,以指示内容是否会延伸到标签之外。

我建议在细胞工厂中这样做,如下所示:

column.setCellFactory(() -> {
    TableCell<?, ?> cell = new TableCell<>();
    cell.setTextOverrun(OverrunStyle.ELLIPSIS);
    return cell;
});

因此,您需要使用单元工厂而不是单元值工厂。我推荐单元工厂的原因是因为表会根据需要自行创建和销毁单元,因此如果您无法像您一样控制这些单元的创建,那么您将很难获取所有这些实例并设置它们的溢出行为做细胞厂。


新尝试

尝试按照这些思路进行操作,您可能需要调整方法以获取字符串的长度,并且您可能希望在更新表格单元格时尝试找出当前单元格的长度,但这应该可以帮助您入门。认为这是一个体面的方法?

public class TestApplication extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }


    public void start(final Stage stage) {
        stage.setResizable(true);

        TestTableView table = new TestTableView();
        ObservableList<String> items = table.getItems();
        items.add("this,is,short,list");
        items.add("this,is,long,list,it,just,keeps,going,on,and,on,and,on");

        Scene scene = new Scene(table, 400, 200);
        stage.setScene(scene);

        stage.show();
    }


    /**
     * Note: this does not take into account font or any styles.
     * <p>
     * You might want to modify this to put the text in a label, apply fonts and css, layout the label,
     * then get the width.
     */
    private static double calculatePixelWidthOfString(String str) {
        return new Text(str).getBoundsInLocal().getWidth();
    }

    public class TestTableView extends TableView<String> {

        public TestTableView() {
            final TableColumn<String, CsvString> column = new TableColumn<>("COL1");
            column.setCellValueFactory(cdf -> {
                return new ReadOnlyObjectWrapper<>(new CsvString(cdf.getValue()));
            });
            column.setCellFactory(col -> {
                return new TableCell<String, CsvString>() {

                    @Override
                    protected void updateItem(CsvString item, boolean empty) { 
                        super.updateItem(item, empty);

                        if (item == null || empty) {
                            setText(null);
                        } else {

                            String text = item.getText();
                            // get the width, might need to tweak this.
                            double textWidth = calculatePixelWidthOfString(text);
                            // might want to compare against current cell width
                            if (textWidth > 100) {
                                // modify the text here
                                text = item.getNumElements() + " elements";
                            }

                            setText(text);
                        }
                    }
                };
            });
            this.getColumns().add(column);
        }
    }

    private static class CsvString {

        private final String text;
        private final String[] elements;


        public CsvString(String string) {
            Objects.requireNonNull(string);
            this.text = string;
            this.elements = string.split(" *, *");
        }


        public int getNumElements() {
            return elements.length;
        }


        public String getText() {
            return text;
        }
    }
}

推荐阅读