JavaFx canvas filltext 渲染质量
JavaFx canvas filltext rendering quality
我正在开发一个使用 canvas 表示图表的 JavaFx 应用程序。 canvas 正在使用 graphicsContext.fillText() 绘制文本。下图中右边是canvas,左边是使用相同字体的Label。我的问题是我应该使用哪个 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%(笔记本的默认值)。
我在 Canvas
中的文本呈现质量也很差。我用小字体显示密集的文字,之前看起来很丑。
这可能与您 运行 遇到的问题相同,也可能不同,因为我的 Windows 缩放比例为 100%,但我发现在我的案例中它是由Canvas
没有使用与其余 UI 小部件相同的 ClearType 实现。它似乎设置为 GREY
模式而不是 LCD
。这是一个简单的一行修复:
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFontSmoothingType(FontSmoothingType.LCD);
gc.setFont(Font.font("Consolas", 10));
gc.fillText("Example ABC 123", 10, 10);
这是结果,在每种情况下,顶行是渲染版本,底行是场景中的 Label
。我提供了一个放大版本,您可以清楚地看到 Canvas 没有正确进行 LCD 子像素渲染
在右手柄示例中,它们看起来是相同的,我的视觉质量恢复了。
我正在开发一个使用 canvas 表示图表的 JavaFx 应用程序。 canvas 正在使用 graphicsContext.fillText() 绘制文本。下图中右边是canvas,左边是使用相同字体的Label。我的问题是我应该使用哪个 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%(笔记本的默认值)。
我在 Canvas
中的文本呈现质量也很差。我用小字体显示密集的文字,之前看起来很丑。
这可能与您 运行 遇到的问题相同,也可能不同,因为我的 Windows 缩放比例为 100%,但我发现在我的案例中它是由Canvas
没有使用与其余 UI 小部件相同的 ClearType 实现。它似乎设置为 GREY
模式而不是 LCD
。这是一个简单的一行修复:
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFontSmoothingType(FontSmoothingType.LCD);
gc.setFont(Font.font("Consolas", 10));
gc.fillText("Example ABC 123", 10, 10);
这是结果,在每种情况下,顶行是渲染版本,底行是场景中的 Label
。我提供了一个放大版本,您可以清楚地看到 Canvas 没有正确进行 LCD 子像素渲染
在右手柄示例中,它们看起来是相同的,我的视觉质量恢复了。