JavaFX FontMetrics [英] JavaFX FontMetrics
本文介绍了JavaFX FontMetrics的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
这个测试提出了以下问题:
- 为什么上升值(顶部黑线)这么高?我预计它会穿越'T'的顶部。品红线是'lineheight'值,所以我假设它是上面任何文本的基线。
- 如果黑线包含行间距,为什么没有测量顶部的'T'?
- 有没有办法得到一个精确的边界框,或者是否必须以图形的方式扫描文本图像以找到边界?很明显,左值和右值还包括某种间距,所以扫描似乎是唯一的解决方案。
经过一番尝试,我想出了这个解决方案:
p>
这是产生它的代码:
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); //只是一个abitrary颜色
gc.setTextBaseline(VPos.TOP); //这节省了扫描底部
gc.setFont(myFont);
gc.fillText(s,-fm.getLeading(),0); //不必扫描左边
//获取画布快照
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;
//自上而下扫描,直到找到红色像素为止
boolean found = false;
while(y< h&!found){
x = 0;
while(x found = pr.getColor(x,y).equals(Color.RED);
x ++;
}
y ++;
}
int yPos = y - 2;
//从右向左扫描,直到找到一个红色像素
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;
//这是边界框的可见表示形式
Rectangle mask = new Rectangle(0,yPos,xPos,h - yPos);
mask.setFill(Color.rgb(0,0,255,0.25));
root.getChildren()。addAll(canvas,mask); // root是一个全局AnchorPane
System.out.println(边框的宽度是+ xPos);
System.out.println(边界框的高度是+(h - yPos));
$ / code>
FontMetrics需要两次导入:
import com.sun.javafx.tk.FontMetrics;
import com.sun.javafx.tk.Toolkit;
并像这样调用边界框:
Font myFont = new Font(Arial,100.0);
getBoundingBox(Testing,myFont);
它解决了我的问题,我希望这对其他人也有用。
I'm trying to place text accurately in the centre of a pane both horizontally and vertically. Using fontmetrics and a test program I get the following results:
This test raises the following questions:
- Why is the ascent value (top black line) so high? I expected it to go across the top of the 'T'. The magenta line is the 'lineheight' value, so I assume that's the baseline for any text above it.
- If the black line includes line spacing, why is there no measurement for the top of the 'T'?
- Is there a way to get an accurate bounding box or do I have to graphically linescan a text image to find the boundaries? Obviously the left and right values also include some sort of spacing, so a scan would seem to be the only solution.
解决方案
After a bit of experimenting I've come up with this solution:
Here is the code that produces it:
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));
}
Two imports are required for FontMetrics:
import com.sun.javafx.tk.FontMetrics;
import com.sun.javafx.tk.Toolkit;
and call the boundingbox like this for example:
Font myFont = new Font("Arial", 100.0);
getBoundingBox("Testing", myFont);
It solves my problem and I hope this is useful for others as well.
这篇关于JavaFX FontMetrics的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文