简体   繁体   中英

How to draw an 1 pixel line using Javafx Canvas?

I've been googling and searching, found some some related questions/posts but none of the address my problem.

I am drawing lines directly on canvas (JavaFX) using:

gc.setStroke(color);
gc.setLineWidth(lineWidth);
gc.strokeLine(startX, startY, endX, endY);

I want 1 pixel width lines. So I set lineWidth=1. I get this:在此处输入图片说明

Note that the lines are blurred. It is not 1 pixel. I've tried to set lineWidth to 0.1 or 0.01, etc. It does not change the result.

By the way... I do not understand why this parameter is a double. I read somewhere that it has to do with DPI. But I do not understand what is the unit and how it is converted to pixels. Oracle's documentation does not help. (or I did not find the one that helps)

I'd like to get this instead:

在此处输入图片说明

This was implemented in another platform. Note that lines are sharp and have just one 1 pixel.

Imagine each pixel as a (small) rectangle (instead of a point). The integer coordinates are the boundaries between pixels; so a (horizontal or vertical) line with integer coordinates falls "between pixels". This is rendered via antialising, approximating half of the line on one pixel and half on the other. Moving the line 0.5 pixels left or right moves it to the center of the pixel, getting around the issue.

Here's a sample:

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

And the results:

在此处输入图片说明

Use coordinates in this notation x.5.

Look my example:

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

You will get two squares, the second sharp.

Reference: https://dlsc.com/2014/04/10/javafx-tip-2-sharp-drawing-with-canvas-api/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM