问题描述
我在设置文字大小时遇到麻烦.尽管我在此处找到了一种方法计算这个,计算仍然不准确,如本示例所示.
I'm having trouble setting the text size. Although I have found a way here to calculate this, the calculation is still inaccurate, as this example shows.
import java.awt.Toolkit;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class TextHeight extends javafx.application.Application {
@Override
public void start(Stage stage) {
var text = new Text("EXAMPLE");
var fontSize = 100 * Toolkit.getDefaultToolkit().getScreenResolution() / 72.0;
text.setFont(Font.loadFont(getClass().getResourceAsStream("GT Pressura Mono Regular Regular.ttf"), fontSize));
text.setFill(Color.BLUE);
text.setX(0);
text.setY(100);
var pane = new Pane(text, new Rectangle(500, 0, 10, 100));
stage.setScene(new Scene(pane, 600, 120));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我现在根本不想解决文本的位置.只是字体的高度不是100px,而是大约94px.
I don't want to solve the position of the text at all now. It's just that the font doesn't have a height of 100px, but about 94px.
尺寸计算是否存在问题?还是和字体有关? (我在此处下载了它)还是在其他地方出现了问题?
Is there a problem in the size calculation? Or is it related to the font? (I downloaded it here) Or is the problem somewhere else?
请帮助
谢谢
推荐答案
正如评论中所指出的(带有对字体度量的真正出色讨论的链接),字体的大小不是其大写字母的高度
As pointed out in a comment (with a link to a truly excellent discussion of font metrics), the size of a font is not the height of its capital letters.
可能(我想看看其他建议)实现您想要的最佳方法是定义一个自定义Region
来保存您的文本节点,该文本节点将覆盖layoutChildren()
以便它会调整字体大小,以使高度适合该区域的大小.
Probably (I would be interested to see other suggestions) the best way to achieve what you want is to define a custom Region
to hold your text node, which overrides layoutChildren()
so that it adjusts the font size so that the height fits the size of the region.
一些实施说明:
-
Text.setBoundsType()
确定如何测量文本的边界.默认值为LOGICAL
,它将边界基于字体的度量标准,而不是实际呈现的文本.我认为您在这里想要的是VISUAL
边界. - 此实现的内容偏向垂直;表示其宽度取决于其高度.知道高度后,将计算字体大小,并将首选宽度计算为文本的宽度.
Text.setBoundsType()
determines how the bounds of the text are measured. The default isLOGICAL
, which bases the bounds on the metrics of the font, rather than the actual text being rendered. I think what you want here areVISUAL
bounds.- This implementation is content-biased to vertical; meaning that its width depends on its height. Once the height is known, the font size is computed and the preferred width is calculated as the width of the text.
这在一定程度上是受限制的(没有多行文本等),但是如果您想要更复杂的内容,应该为您提供一个起点.
This is somewhat limited (no multiline text, etc.) but should give you a starting point if you want something more sophisticated.
public class TextPane extends Region {
private final Text text ;
public TextPane(Text text) {
this.text = text ;
getChildren().add(text);
}
@Override
protected void layoutChildren() {
adjustFontSize(getHeight());
text.setY(getHeight());
text.setX(0);
}
private void adjustFontSize(double height) {
double textHeight = text.getBoundsInLocal().getHeight();
if (Math.abs(height - textHeight) > 1) {
Font currentFont = text.getFont() ;
double fontSize = currentFont.getSize() ;
text.setFont(Font.font(currentFont.getFamily(), height * fontSize / textHeight));
}
}
@Override
protected double computePrefWidth(double height) {
adjustFontSize(height);
return text.getBoundsInLocal().getWidth();
}
@Override
public Orientation getContentBias() {
return Orientation.VERTICAL;
}
}
这是一个示例,该示例通过将文本窗格的高度固定为100
:
Here's an example which basically implements what you were looking to do, by fixing the height of the text pane to 100
:
public class TextHeight extends javafx.application.Application {
@Override
public void start(Stage stage) {
Text text = new Text("EXAMPLE");
text.setBoundsType(TextBoundsType.VISUAL);
text.setTextOrigin(VPos.BOTTOM);
text.setFill(Color.BLUE);
TextPane textPane = new TextPane(text);
textPane.setMinHeight(100);
textPane.setMaxHeight(100);
Pane root = new Pane(textPane, new Rectangle(620, 0, 10, 100));
stage.setScene(new Scene(root, 700, 120));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
如果文本具有下降的字形(例如,如果将"EXAMPLE"
更改为"Example"
,因此p
下降到基线以下),则文本的总高度将包括下降:
If the text has glyphs with descent (e.g. if you change "EXAMPLE"
to "Example"
, so the p
descends below the baseline), the total height of the text will include the descent:
这是一个使用文本窗格作为根节点的示例(因此,其大小始终与场景相同).更改窗口大小将导致文本自动更新以垂直填充场景:
And here's an example which uses the text pane as the root node (so it's always the same size as the scene). Changing the window size will result in the text automatically updating to vertically fill the scene:
public class TextHeight extends javafx.application.Application {
@Override
public void start(Stage stage) {
Text text = new Text("Example");
text.setBoundsType(TextBoundsType.VISUAL);
text.setTextOrigin(VPos.BOTTOM);
text.setFill(Color.BLUE);
TextPane textPane = new TextPane(text);
textPane.setPrefHeight(100);
stage.setScene(new Scene(textPane));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这篇关于正确设置文本大小(以像素为单位)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!