JavaFX FontMetrics [英] JavaFX FontMetrics

查看:188
本文介绍了JavaFX FontMetrics的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将文本在水平和垂直方向上精确放置在窗格的中心。使用fontmetrics和测试程序,我得到以下结果:



这个测试提出了以​​下问题:


  1. 为什么上升值(顶部黑线)这么高?我预计它会穿越'T'的顶部。品红线是'lineheight'值,所以我假设它是上面任何文本的基线。

  2. 如果黑线包含行间距,为什么没有测量顶部的'T'?

  3. 有没有办法得到一个精确的边界框,或者是否必须以图形的方式扫描文本图像以找到边界?很明显,左值和右值还包括某种间距,所以扫描似乎是唯一的解决方案。

经过一番尝试,我想出了这个解决方案:



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:

  1. 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.
  2. If the black line includes line spacing, why is there no measurement for the top of the 'T'?
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆