【问题标题】:Correct setting of the text size in pixels正确设置文本大小(以像素为单位)
【发布时间】:2020-12-14 10:21:43
【问题描述】:

我无法设置文字大小。虽然我找到了一种方法here 来计算这个,但计算仍然不准确,如本例所示。

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左右。

尺寸计算有问题吗?还是和字体有关? (我下载了here)还是其他地方有问题?

请帮忙

谢谢

【问题讨论】:

标签: java javafx pixel font-size


【解决方案1】:

正如评论中所指出的(带有指向真正出色的字体度量讨论的链接),字体的大小不是其大写字母的高度。

可能(我有兴趣看到其他建议)实现您想要的最佳方法是定义一个自定义 Region 来保存您的文本节点,它会覆盖 layoutChildren() 以便它调整字体大小,使高度适合区域的大小。

几个实现说明:

  • Text.setBoundsType() 确定如何测量文本的边界。默认值为LOGICAL,它的边界基于字体的度量,而不是实际呈现的文本。我认为你想要的是VISUAL bounds。
  • 此实现内容偏向于垂直;这意味着它的宽度取决于它的高度。一旦知道高度,就会计算字体大小,并将首选宽度计算为文本的宽度。

这有点有限(没有多行文本等),但如果你想要更复杂的东西,应该给你一个起点。

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,基本上实现了您想要做的事情:

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 下降到基线以下),文本的总高度将包括下降:

这是一个使用文本窗格作为根节点的示例(因此它始终与场景大小相同)。更改窗口大小将导致文本自动更新以垂直填充场景:

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);
    }
}

【讨论】:

  • 这正是我想要的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 2018-07-04
  • 2020-02-16
  • 2010-11-06
  • 2015-07-01
相关资源
最近更新 更多