如何使用 Javafx Canvas 绘制 1 像素的线?
How to draw an 1 pixel line using Javafx Canvas?
我一直在谷歌搜索,找到了一些相关的 questions/posts 但 none 解决了我的问题。
我直接在 canvas (JavaFX) 上画线使用:
gc.setStroke(color);
gc.setLineWidth(lineWidth);
gc.strokeLine(startX, startY, endX, endY);
我想要 1 像素宽的线条。所以我设置lineWidth=1。
我明白了:
请注意线条是模糊的。它不是 1 个像素。
我尝试将 lineWidth 设置为 0.1 或 0.01 等。它不会改变结果。
顺便说一句...我不明白为什么这个参数是双精度的。我在某处读到它与 DPI 有关。但是我不明白什么是单位以及如何将其转换为像素。
Oracle 的文档没有帮助。 (或者我没有找到有用的)
我想要这个:
这是在另一个平台上实现的。请注意,线条很清晰,只有一个 1 像素。
将每个像素想象成一个(小)矩形(而不是一个点)。整数坐标是像素之间的边界;因此,具有整数坐标的(水平或垂直)线落在“像素之间”。这是通过抗锯齿渲染的,在一个像素上近似一半的线,在另一个像素上近似一半。将线条向左或向右移动 0.5 个像素会将其移动到像素的中心,从而解决问题。
这是一个示例:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SharpCanvasTest extends Application {
@Override
public void start(Stage primaryStage) {
Canvas sharpCanvas = createCanvasGrid(600, 300, true);
Canvas blurryCanvas = createCanvasGrid(600, 300, false);
VBox root = new VBox(5, sharpCanvas, blurryCanvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private Canvas createCanvasGrid(int width, int height, boolean sharp) {
Canvas canvas = new Canvas(width, height);
GraphicsContext gc = canvas.getGraphicsContext2D() ;
gc.setLineWidth(1.0);
for (double x = sharp ? 0.5 : 0.0; x < width; x+=10) {
gc.moveTo(x, 0);
gc.lineTo(x, height);
gc.stroke();
}
for (double y = sharp ? 0.5 : 0.0; y < height; y+=10) {
gc.moveTo(0, y);
gc.lineTo(width, y);
gc.stroke();
}
return canvas ;
}
public static void main(String[] args) {
launch(args);
}
}
结果:
在此表示法中使用坐标 x.5。
看我的例子:
gc.setFill(Color.BLACK);
gc.setLineWidth(1.0);
gc.strokeRect(50, 100, 25.0, 25.0);
gc.strokeRect(100.5, 100.5, 25.0, 25.0);
你会得到两个正方形,第二个正方形。
参考:https://dlsc.com/2014/04/10/javafx-tip-2-sharp-drawing-with-canvas-api/
我一直在谷歌搜索,找到了一些相关的 questions/posts 但 none 解决了我的问题。
我直接在 canvas (JavaFX) 上画线使用:
gc.setStroke(color);
gc.setLineWidth(lineWidth);
gc.strokeLine(startX, startY, endX, endY);
我想要 1 像素宽的线条。所以我设置lineWidth=1。
我明白了:
请注意线条是模糊的。它不是 1 个像素。 我尝试将 lineWidth 设置为 0.1 或 0.01 等。它不会改变结果。
顺便说一句...我不明白为什么这个参数是双精度的。我在某处读到它与 DPI 有关。但是我不明白什么是单位以及如何将其转换为像素。 Oracle 的文档没有帮助。 (或者我没有找到有用的)
我想要这个:
这是在另一个平台上实现的。请注意,线条很清晰,只有一个 1 像素。
将每个像素想象成一个(小)矩形(而不是一个点)。整数坐标是像素之间的边界;因此,具有整数坐标的(水平或垂直)线落在“像素之间”。这是通过抗锯齿渲染的,在一个像素上近似一半的线,在另一个像素上近似一半。将线条向左或向右移动 0.5 个像素会将其移动到像素的中心,从而解决问题。
这是一个示例:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SharpCanvasTest extends Application {
@Override
public void start(Stage primaryStage) {
Canvas sharpCanvas = createCanvasGrid(600, 300, true);
Canvas blurryCanvas = createCanvasGrid(600, 300, false);
VBox root = new VBox(5, sharpCanvas, blurryCanvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private Canvas createCanvasGrid(int width, int height, boolean sharp) {
Canvas canvas = new Canvas(width, height);
GraphicsContext gc = canvas.getGraphicsContext2D() ;
gc.setLineWidth(1.0);
for (double x = sharp ? 0.5 : 0.0; x < width; x+=10) {
gc.moveTo(x, 0);
gc.lineTo(x, height);
gc.stroke();
}
for (double y = sharp ? 0.5 : 0.0; y < height; y+=10) {
gc.moveTo(0, y);
gc.lineTo(width, y);
gc.stroke();
}
return canvas ;
}
public static void main(String[] args) {
launch(args);
}
}
结果:
在此表示法中使用坐标 x.5。
看我的例子:
gc.setFill(Color.BLACK);
gc.setLineWidth(1.0);
gc.strokeRect(50, 100, 25.0, 25.0);
gc.strokeRect(100.5, 100.5, 25.0, 25.0);
你会得到两个正方形,第二个正方形。
参考:https://dlsc.com/2014/04/10/javafx-tip-2-sharp-drawing-with-canvas-api/