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

如何在JavaFX TableView中实现鼠标悬停放大TableCell效果?

JavaFX TableView实现鼠标悬停放大单元格效果

需求说明

需要实现类似Swing的表格单元格悬停放大功能:未悬停时单元格受列宽限制,鼠标悬停时自动展开,完整显示单元格内的文本内容。

实现方案

通过自定义TableCell,监听鼠标的进入/退出事件,动态计算文本的实际宽度并调整单元格尺寸,具体实现如下:

import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.util.List;

public class ExpandingLabelApp2 extends Application {
    @Override
    public void start(Stage stage) {
        TableView<Lines> tableView = new TableView<>(createTestData());

        TableColumn<Lines, String> col1 = new TableColumn<>("操作说明1");
        col1.setCellValueFactory(p -> readOnlyStringProperty(p.getValue().line1));
        col1.setCellFactory(p -> new ExpandingTableCell<>());
        col1.setMaxWidth(120);

        TableColumn<Lines, String> col2 = new TableColumn<>("操作说明2");
        col2.setCellValueFactory(p -> readOnlyStringProperty(p.getValue().line2));

        tableView.getColumns().setAll(List.of(col1, col2));
        tableView.setPrefSize(500, 200);

        stage.setScene(new Scene(tableView));
        stage.setTitle("悬停放大单元格示例");
        stage.show();
    }

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

    private static ReadOnlyStringProperty readOnlyStringProperty(String string) {
        return new ReadOnlyStringWrapper(string).getReadOnlyProperty();
    }

    private static ObservableList<Lines> createTestData() {
        ObservableList<Lines> lines = FXCollections.observableArrayList();
        List<String> testContent = """
                Double, double toil and trouble;
                Fire burn and caldron bubble.
                Fillet of a fenny snake,
                In the caldron boil and bake;
                Eye of newt and toe of frog,
                Wool of bat and tongue of dog,
                Adder's fork and blind-worm's sting,
                Lizard's leg and howlet's wing,
                For a charm of powerful trouble,
                Like a hell-broth boil and bubble.
                Double, double toil and trouble;
                Fire burn and caldron bubble.
                Cool it with a baboon's blood,
                Then the charm is firm and good.
                """.lines().toList();

        for (int i = 0; i < testContent.size(); i += 2) {
            String line1 = testContent.get(i);
            String line2 = i + 1 < testContent.size() ? testContent.get(i + 1) : "";
            lines.add(new Lines(line1, line2));
        }
        return lines;
    }

    record Lines(String line1, String line2) {}

    public class ExpandingTableCell<S> extends TableCell<S, String> {

        public ExpandingTableCell() {
            super();
            // 鼠标进入时展开单元格
            setOnMouseEntered(ev -> {
                if (!isEmpty() && getItem() != null) {
                    // 计算文本的实际宽度
                    Text text = new Text(getItem());
                    text.setFont(getFont());
                    double textWidth = text.getLayoutBounds().getWidth();
                    // 设置单元格宽度为文本实际宽度,留出一点边距
                    setPrefWidth(textWidth + 10);
                    setManaged(false);
                }
            });
            // 鼠标退出时恢复原状态
            setOnMouseExited(e -> {
                if (!isManaged()) {
                    setManaged(true);
                    setPrefWidth(USE_COMPUTED_SIZE);
                }
            });
        }

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (item == null || empty) {
                setText(null);
            } else {
                setText(item);
            }
        }
    }
}

关键实现细节

  • 文本宽度计算:使用Text组件加载单元格文本,通过getLayoutBounds().getWidth()获取文本的实际渲染宽度,确保单元格能刚好容纳完整文本。
  • 单元格管理状态:设置setManaged(false)可以让单元格脱离TableColumn的宽度限制,自由调整自身尺寸;退出悬停时恢复managed状态,回到列宽限制下的显示。
  • 边距预留:在计算出的文本宽度基础上加10个像素的边距,避免文本紧贴单元格边缘,提升视觉体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:00:56