2

我正在开发一个使用画布表示图表的 JavaFx 应用程序。画布正在使用 graphicsContext.fillText() 绘制文本。在下图中,画布在右侧,左侧是使用相同字体的标签。我的问题是我应该使用哪个 renering 参数来使右侧文本看起来与左侧相同?

使用等宽字体的标签与画布

public class SampleRenderingIssue extends Application {
    private final StackPane root = new StackPane();
    private final Scene scene = new Scene(root, 300, 250);
    private final BorderPane pane = new BorderPane();
    private final Canvas canvas = new Canvas();


    @Override
    public void start(Stage stage) {
        stage.setTitle("Sample Canvas");

        VBox vbox = new VBox();
        VBox.setVgrow(pane, Priority.ALWAYS);
        vbox.getChildren().addAll( pane );

        pane.getChildren().add(canvas);
        root.getChildren().add(vbox);
        stage.setScene(scene);
        stage.sizeToScene();
        setupCanvasPane();
        stage.show();
        Platform.runLater(()-> paint());
    }
    private void setupCanvasPane(){
        canvas.widthProperty().bind(pane.widthProperty());
        canvas.heightProperty().bind(pane.heightProperty());
        pane.widthProperty().addListener((o,p,c)-> paint());
        paint();
    }

    public void paint(){
        GraphicsContext gr = canvas.getGraphicsContext2D();
        gr.clearRect( 0,0, canvas.getWidth(), canvas.getHeight() );
        gr.setFill( Color.web("#222222") );
        gr.fillRect( 0,0,canvas.getWidth(), canvas.getHeight());
        gr.setStroke( Color.WHITE );
        gr.setFill( Color.WHITE );
        gr.setLineWidth( 1d );
        gr.strokeLine( 0,0, canvas.getWidth(), canvas.getHeight() );
        gr.setFont( Font.font( "Candara"));
        gr.fillText("This is a text", 100, 100 );
        gr.setFont( Font.font( "Monospaced"));
        gr.fillText("This is a text", 100, 120 );
    }

    public static void main(String[] args) {
        launch(args);
    }

}

该问题在控制面板中的 Windows 比例设置为 125%(笔记本的默认值)的 FullHd 显示器上重现。

在此处输入图像描述

4

1 回答 1

1

我在Canvas. 我以小字体显示密集的文本,以前看起来很丑。

这可能与您遇到的问题相同,也可能不同,因为我的 Windows 缩放率为 100%,但我发现在我的情况下,这是由于Canvas没有使用与 UI 的其余部分相同的 ClearType 实现小部件可以。它似乎设置为GREYmode 而不是LCD. 这是一个简单的单行修复:

        GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.setFontSmoothingType(FontSmoothingType.LCD);
        gc.setFont(Font.font("Consolas", 10));
        gc.fillText("Example ABC 123", 10, 10);

这是结果,在每种情况下,顶行是渲染版本,底行是Label场景中的 a。我已经包含了一个放大版本,您可以清楚地看到 Canvas 没有正确地进行 LCD 子像素渲染

在此处输入图像描述

在右手柄示例中,它们看起来是相同的,并且我的视觉质量得到了恢复。

于 2020-11-25T18:00:39.667 回答