Fonts JavaFXFontMetrics
我试图在水平和垂直方向将文本准确地放置在窗格的中心。使用fontmetrics和测试程序,我得到以下结果: 该测试提出了以下问题:Fonts JavaFXFontMetrics,fonts,javafx,Fonts,Javafx,我试图在水平和垂直方向将文本准确地放置在窗格的中心。使用fontmetrics和测试程序,我得到以下结果: 该测试提出了以下问题: 为什么上升值(黑色顶线)这么高?我以为它会穿过T字的顶端。品红色线是“lineheight”值,因此我假设这是它上面任何文本的基线 如果黑线包括行距,为什么“T”的顶部没有测量值 有没有一种方法可以得到一个精确的边界框,或者我必须用图形化的线条扫描文本图像才能找到边界?显然,左、右值还包含某种间距,因此扫描似乎是唯一的解决方案 经过一点实验,我想出了这个解决方案:
经过一点实验,我想出了这个解决方案: 下面是生成它的代码:
public void getBoundingBox(String s, Font myFont) {
final FontMetrics fm = Toolkit.getToolkit().getFontLoader().getFontMetrics(myFont);
final Canvas canvas = new Canvas(fm.computeStringWidth(s), fm.getAscent() + fm.getDescent());
final GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.RED); // Just an abitrary color
gc.setTextBaseline(VPos.TOP); // This saves having to scan the bottom
gc.setFont(myFont);
gc.fillText(s, -fm.getLeading(), 0); // This saves having to scan the left
// Get a snapshot of the canvas
final WritableImage image = canvas.snapshot(null, null);
final PixelReader pr = image.getPixelReader();
final int h = (int) canvas.getHeight();
final int w = (int) canvas.getWidth();
int x;
int y = 0;
// Scan from the top down until we find a red pixel
boolean found = false;
while (y < h && !found) {
x = 0;
while (x < w && !found) {
found = pr.getColor(x, y).equals(Color.RED);
x++;
}
y++;
}
int yPos = y - 2;
// Scan from right to left until we find a red pixel
x = w;
found = false;
while (x > 0 && !found) {
y = 0;
while (y < h && !found) {
found = pr.getColor(x, y).equals(Color.RED);
y++;
}
x--;
}
int xPos = x + 3;
// Here is a visible representation of the bounding box
Rectangle mask = new Rectangle(0, yPos, xPos, h - yPos);
mask.setFill(Color.rgb(0, 0, 255, 0.25));
root.getChildren().addAll(canvas, mask); // root is a global AnchorPane
System.out.println("The width of the bounding box is " + xPos);
System.out.println("The height of the bounding box is " + (h - yPos));
}
并按如下方式调用边界框,例如:
Font myFont = new Font("Arial", 100.0);
getBoundingBox("Testing", myFont);
它解决了我的问题,我希望这对其他人也有用。以下是Frank的
reportSize
函数的替代实现:
public void reportSize(String s, Font myFont) {
Text text = new Text(s);
text.setFont(myFont);
Bounds tb = text.getBoundsInLocal();
Rectangle stencil = new Rectangle(
tb.getMinX(), tb.getMinY(), tb.getWidth(), tb.getHeight()
);
Shape intersection = Shape.intersect(text, stencil);
Bounds ib = intersection.getBoundsInLocal();
System.out.println(
"Text size: " + ib.getWidth() + ", " + ib.getHeight()
);
}
此实现使用来确定渲染形状的边界框的大小(不带空格)。该实现不依赖于Java 9+中的用户应用程序代码可能无法直接访问的
com.sun
包类 请看。谢谢,我已经看到了,但是getMaxAscent()与getAscent()的值相同,并且不是从基线到角色顶部的距离。它给出了我上图中的黑色顶线。该字体中没有延伸到黑线的字符。此问题被标记为javafx
,是否应该?据我所知,字体度量数据未在中公开,因此该问题似乎与JavaFX没有直接关系。您可能希望通过在问题中放置代码来共享您的测试程序。弗兰克:正确。“是从下行线底部到下一行顶部的建议距离。”如您所述,我已成功使用Toolkit.getToolkit().getFontLoader().getFontMetrics(..),但com.sun.javafx.tk.Toolkit以及com.sun.javafx.tk.FontMetrics是“内部”包。有人知道只使用公共javafx.*包获得同等信息的方法吗?另请参见Java9中的fm.computeStringWidth(String)已替换为getCharWidth(char),因此此示例不再有效。
public void reportSize(String s, Font myFont) {
Text text = new Text(s);
text.setFont(myFont);
Bounds tb = text.getBoundsInLocal();
Rectangle stencil = new Rectangle(
tb.getMinX(), tb.getMinY(), tb.getWidth(), tb.getHeight()
);
Shape intersection = Shape.intersect(text, stencil);
Bounds ib = intersection.getBoundsInLocal();
System.out.println(
"Text size: " + ib.getWidth() + ", " + ib.getHeight()
);
}