已知字体大小,如何在JavaFX中获取含Text组件的行高?
关于JavaFX中HBox内Text节点提前获取精确高度及消除行高差值的问题
我在HBox中使用了Text节点,需要在该行显示前获取其精确高度(不使用pulse监听器)。测试代码如下:
public class Test1 extends Application { @Override public void start(Stage primaryStage) { Font systemFont = Font.font("System", 14); VBox root = new VBox( createBox("red", systemFont), createBox("yellow", systemFont), createBox("red", systemFont) ); Scene scene = new Scene(root, 300, 200); primaryStage.setScene(scene); primaryStage.show(); } private HBox createBox(String color, Font font) { var hBox = new HBox(); hBox.setStyle("-fx-padding: 0; -fx-background-color: " + color); var text = new Text("Hello, World!"); text.setFont(font); hBox.getChildren().add(text); hBox.heightProperty().addListener((ov, oldV, newV) -> System.out.println("NewHeight:" + newV)); return hBox; } public static void main(String[] args) { launch(args); } }
运行后输出为:
NewHeight:17.0 NewHeight:17.0 NewHeight:17.0
可见字体大小为14时,行高为17,每行存在3像素差值。请问如何提前计算该差值,或消除此差值?
解决方案
一、提前计算Text的精确高度(无需等待布局完成)
Text节点的实际高度可以通过getBoundsInLocal()方法直接获取,该方法在Text的内容和字体设置完成后,就能返回精确的自身边界信息,不需要依赖布局脉冲监听器:
修改createBox方法,添加以下代码即可提前获取高度:
// 设置Text内容和字体后,直接获取精确高度 Bounds textBounds = text.getBoundsInLocal(); double exactTextHeight = textBounds.getHeight(); System.out.println("精确Text高度:" + exactTextHeight);
这里返回的高度是Text本身的像素高度,对于14号系统字体,通常会得到接近14的数值。HBox高度为17的原因,是其默认的基线对齐方式和Text的基线偏移导致了额外间距。
二、消除HBox与Text的高度差值
要让HBox高度完全匹配Text的精确高度,需要调整两个核心点:
- 取消HBox默认的基线对齐,改为顶部对齐
- 修正Text的基线偏移带来的顶部空隙
修改后的createBox方法如下:
private HBox createBox(String color, Font font) { var hBox = new HBox(); hBox.setStyle("-fx-padding: 0; -fx-background-color: " + color); // 更改对齐方式为顶部左对齐,取消基线对齐 hBox.setAlignment(Pos.TOP_LEFT); var text = new Text("Hello, World!"); text.setFont(font); // 计算并抵消Text的基线偏移空隙 double baselineOffset = text.getBaselineOffset(); double topGap = baselineOffset - text.getBoundsInLocal().getHeight(); text.setTranslateY(-topGap); hBox.getChildren().add(text); hBox.heightProperty().addListener((ov, oldV, newV) -> System.out.println("NewHeight:" + newV)); // 提前获取Text精确高度 Bounds textBounds = text.getBoundsInLocal(); System.out.println("精确Text高度:" + textBounds.getHeight()); return hBox; }
修改后运行,HBox的高度会与Text的精确高度一致,输出的NewHeight会接近14(具体数值取决于系统字体的实际渲染)。
补充说明
getBoundsInLocal()返回的是节点自身坐标系下的边界,不受父容器布局影响,适合提前计算尺寸- HBox默认使用
Pos.BASELINE_LEFT对齐,会为文本基线预留空间,这是导致高度差的主要原因 - Text的
baselineOffset是文本基线到节点顶部的距离,减去文本自身高度就是顶部的空隙,通过负的TranslateY可以抵消这个空隙
内容的提问来源于stack exchange,提问作者SilverCube
相关产品推荐
相关产品推荐

