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

如何通过代码(非FXML)实现JavaFX TableColumn表头左对齐?

JavaFX 17 实现单个TableColumn表头对齐(程序化方式)

问题描述

我在JavaFX 17中尝试将TableColumn表头设置为左对齐,希望通过Java代码(程序化方式)实现,不使用FXML。我可以通过为场景添加Base64编码的样式表URL全局设置对齐,但不知道如何仅修改单个TableColumn表头的对齐方式。尝试通过setStyle(...)设置各类CSS均无效。

解决方案

感谢@DavidWeber的帮助,我采纳了他的建议(并使用了JDK switch/null预览特性)。以下是最终实现代码:

package com.stackoverflow.question;

import java.util.function.Function;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.transformation.SortedList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.skin.TableColumnHeader;
import javafx.stage.Stage;

public final class TableColumnAlignment extends Application {

    private record RowData(String left, Integer right) {}

    private static final String TITLE_LEFT  = "Left";
    private static final String TITLE_RIGHT = "Right";

    @Override
    public void start(final Stage stage) throws Exception {

        final var colLeft  = buildColumn("colLeft",  TITLE_LEFT,  RowData :: left);
        final var colRight = buildColumn("colRight", TITLE_RIGHT, RowData :: right);
        ;         colRight.setStyle("-fx-alignment: center-right");
        
        final var sortedList = new SortedList<RowData>(FXCollections.observableArrayList(FXCollections.observableArrayList(
                new RowData("Left Column Header should be Left-Justified!", 123456789),
                new RowData("This Cell is left justified ok",                     789),
                new RowData("Right Column Header should be Right-Justified!",  456789) )));

        final var  table    = new TableView<RowData>();
        ;          table.getColumns().add(colLeft);
        ;          table.getColumns().add(colRight);
        ;          table.setItems(sortedList);
        
        sortedList.comparatorProperty().bind(table.comparatorProperty());
        
        Platform.runLater(() -> {
            table.lookupAll(".column-header > .label").forEach(node -> {
                if (node.getParent()  instanceof  TableColumnHeader
                &&  node              instanceof  Label              nodeLabel) {
                    switch(nodeLabel.getText()) {
                        case TITLE_LEFT  -> nodeLabel.setAlignment(Pos.CENTER_LEFT);
                        case TITLE_RIGHT -> nodeLabel.setAlignment(Pos.CENTER_RIGHT);
                    }
                    System.out.println(nodeLabel + "\t" + nodeLabel.getText());
                }
            });
        });
        stage.setTitle("Table Column Alignment");
        stage.setScene(new Scene(table, 500, 200));
        stage.show();
    }

    private <T, V> TableColumn<T, V> buildColumn(final String id, final String title, final Function<T, V> getter) {

        final var tableColumn = new TableColumn<T, V>(title);
        ;         tableColumn.setId(id);
        ;         tableColumn.setCellValueFactory((cellDataFeatures) -> {

            final T bean              = cellDataFeatures.getValue();
            final V beanPropertyValue = getter.apply(bean);

            return new ReadOnlyObjectWrapper<V>(beanPropertyValue);
        });
        return    tableColumn;
    }

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

核心思路

  • 使用Platform.runLater()确保UI组件渲染完成后再操作表头元素,避免出现查找不到节点的情况
  • 通过lookupAll(".column-header > .label")定位所有表头的Label组件
  • 根据表头文本匹配目标列,调用Label.setAlignment()单独设置对应表头的对齐方式

原始问题代码

package com.stackoverflow.question;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public final class TableColumnAlignment extends Application {

    private record RowData(String left, Integer right) {}

    @Override
    public void start(final Stage stage) throws Exception {

        final var       colLeft  = buildTableColumn("Left",  RowData :: left);
        final var       colRight = buildTableColumn("Right", RowData :: right);

        colLeft .setId("colLeft");
        colRight.setId("colRight");
        
        colLeft.setStyle("-fx-alignment: center-left; -fx-background-color: yellow");

        final var  table    = new TableView<RowData>();
        addColumns(table.getColumns(), colLeft, colRight);
        ;          table.setItems(FXCollections.observableArrayList(
                new RowData("Left Column Header should be Left-Justified!", 123456789),
                new RowData("This Cell is left justified ok",                     789),
                new RowData("Right Column Header should be Right-Justified!",  456789) ));

        final var  scene    = new Scene(table, 500, 200);
//      ;          scene.getStylesheets().add(encodeStyleAsURL(".column-header .label {-fx-alignment: center-left}"));
        
        stage.setTitle("Table Column Alignment");
        stage.setScene(scene);
        stage.show();
    }

    public  static String encodeStyleAsURL(final String cssStyle) {

        final var cssBytes       = cssStyle.getBytes(StandardCharsets.UTF_8);
        final var cssBytesBase64 = Base64.getEncoder().encodeToString(cssBytes);

        return    "data:text/css;base64," + cssBytesBase64;
    }

    private <T, V> TableColumn<T, V> buildTableColumn(final String title, final Function<T, V> beanPropertyGetter) {

        final var tableColumn = new TableColumn<T, V>(title);
        ;         tableColumn.setCellValueFactory((cellDataFeatures) -> {

            final T bean              = cellDataFeatures.getValue();
            final V beanPropertyValue = beanPropertyGetter.apply(bean);

            return new ReadOnlyObjectWrapper<V>(beanPropertyValue);
        });
        return    tableColumn;
    }

    @SafeVarargs
    private final <T> void addColumns(final ObservableList<TableColumn<T, ?>> columnList, final TableColumn<T, ?>... columns) {
        columnList.addAll(columns);
    }

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

内容的提问来源于stack exchange,提问作者Dave The Dane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 06:44:55