You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaFX的TableView中创建带前置省略号的列?

实现JavaFX TableView路径列的前置省略号显示

需求:TableView中存储路径的列,所有路径属于同一根目录,当路径长度超出列宽时,仅显示路径末尾并添加前置省略号,示例:

..someverylongdirectoryname/file.txt
..omeverylongdirectoryname/file2.txt

尝试的代码未能实现预期效果:

public class JavaFxTest extends Application {


    public static class FilePath {
        private final String path;

        public FilePath(String path) {
            this.path = path;
        }

        public String getPath() {
            return path;
        }
    }

    @Override
    public void start(Stage primaryStage) {
        TableView<FilePath> tableView = new TableView<>();

        TableColumn<FilePath, String> pathColumn = new TableColumn<>("Path");
        pathColumn.setCellValueFactory(new PropertyValueFactory<>("path"));
        pathColumn.setPrefWidth(200);

        pathColumn.setCellFactory(column -> new javafx.scene.control.TableCell<>() {
            private final Text text = new Text();

            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (empty || item == null) {
                    setGraphic(null);
                } else {
                    text.setText(item);
                    text.setStyle("-fx-text-alignment: right;");
                    setGraphic(text);
                }
            }
        });

        tableView.getColumns().add(pathColumn);
        tableView.getItems().addAll(
            new FilePath("/usr/local/bin/someverylongdirectoryname/file.txt"),
            new FilePath("/usr/local/bin/someverylongdirectoryname/file2.txt")
        );

        primaryStage.setScene(new Scene(tableView, 300, 200));
        primaryStage.show();
    }

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

解决方案

要实现前置省略号的效果,需要手动计算文本宽度并截断前缀,同时监听列宽变化以动态更新显示内容。修改后的代码如下:

public class JavaFxTest extends Application {

    public static class FilePath {
        private final String path;

        public FilePath(String path) {
            this.path = path;
        }

        public String getPath() {
            return path;
        }
    }

    @Override
    public void start(Stage primaryStage) {
        TableView<FilePath> tableView = new TableView<>();

        TableColumn<FilePath, String> pathColumn = new TableColumn<>("Path");
        pathColumn.setCellValueFactory(new PropertyValueFactory<>("path"));
        pathColumn.setPrefWidth(200);

        pathColumn.setCellFactory(column -> new TableCell<>() {
            private final Text text = new Text();
            // 保存原始路径,方便列宽变化时重新计算
            private String originalPath;

            {
                // 监听列宽度变化,重新更新显示内容
                column.widthProperty().addListener((obs, oldWidth, newWidth) -> {
                    if (originalPath != null && !isEmpty()) {
                        updateDisplayText(originalPath, newWidth.doubleValue());
                    }
                });
                // 设置文本对齐为右对齐,让末尾内容对齐
                text.setStyle("-fx-text-alignment: right;");
            }

            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (empty || item == null) {
                    setGraphic(null);
                    originalPath = null;
                } else {
                    originalPath = item;
                    updateDisplayText(item, column.getWidth());
                    setGraphic(text);
                }
            }

            private void updateDisplayText(String path, double columnWidth) {
                // 减去TableCell的默认内边距,避免计算误差
                double availableWidth = columnWidth - 10;
                text.setText(path);
                // 如果文本宽度小于等于可用宽度,直接显示
                if (text.getLayoutBounds().getWidth() <= availableWidth) {
                    return;
                }

                // 逐步截断前缀,直到文本宽度符合要求
                String truncatedPath = path;
                // 最小保留长度,避免过度截断
                final int minLength = 10;
                while (text.getLayoutBounds().getWidth() > availableWidth && truncatedPath.length() > minLength) {
                    // 从第一个斜杠后截断,保留末尾并添加前置省略号
                    int firstSlashIndex = truncatedPath.indexOf('/');
                    if (firstSlashIndex == -1) {
                        // 无斜杠时直接从开头截断
                        truncatedPath = ".." + truncatedPath.substring(2);
                    } else {
                        truncatedPath = ".." + truncatedPath.substring(firstSlashIndex + 1);
                    }
                    text.setText(truncatedPath);
                }
            }
        });

        tableView.getColumns().add(pathColumn);
        tableView.getItems().addAll(
                new FilePath("/usr/local/bin/someverylongdirectoryname/file.txt"),
                new FilePath("/usr/local/bin/someverylongdirectoryname/file2.txt")
        );

        primaryStage.setScene(new Scene(tableView, 300, 200));
        primaryStage.show();
    }

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

关键说明

  • 保存原始路径:在TableCell中存储原始路径,避免列宽变化时丢失完整数据。
  • 监听列宽变化:当列宽度调整时,自动重新计算并更新显示文本,保证自适应宽度变化。
  • 动态截断前缀:通过循环逐步截断路径的前缀部分,同时添加..,直到文本宽度符合列宽限制,确保始终显示路径的末尾核心部分。
  • 内边距调整:计算可用宽度时减去TableCell的默认内边距,避免因内边距导致的显示误差。

内容的提问来源于stack exchange,提问作者SilverCube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:23:16