Как нарисовать линию 1 пикселя с помощью JavaFX Canvas?

я гуглил и искал, нашел некоторые связанные вопросы / сообщения, но ни один из адресов моей проблемы.

Я рисую линии непосредственно на холсте (JavaFX), используя:

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

Я хочу линии ширины 1 пиксела. Поэтому я установил lineWidth=1. Я понимаю.: enter image description here

обратите внимание, что линии размыты. Это не 1 пиксель. Я пытался установить ширину линии до 0,1 или 0,01 и т. д. Результат не меняется.

кстати... Я не понимаю, почему этот параметр является двойным. Я где-то читал, что это связано с DPI. Но я не понимаю, что такое единица измерения и как она преобразуется в пиксели. Документация Oracle не помогает. (или я не нашел тот, который помогает)

Я хотел бы получить это вместо этого:

enter image description here

Это было реализовано на другой платформе. Обратите внимание, что линии и всего в 1 пиксель.

1 ответов


представьте каждый пиксель как (маленький) прямоугольник (вместо точки). Целочисленные координаты-это границы между пикселями; поэтому (горизонтальная или вертикальная) линия с целочисленными координатами падает "между пикселями". Это обрабатывается через antialising, аппроксимирующих половине строки по одному пикселю, а половина на другой. Перемещение линии 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 (int x = 0; x < width; x+=10) {
            double x1 ;
            if (sharp) {
                x1 = x + 0.5 ;
            } else {
                x1 = x ;
            }
            gc.moveTo(x1, 0);
            gc.lineTo(x1, height);
            gc.stroke();
        }

        for (int y = 0; y < height; y+=10) {
            double y1 ;
            if (sharp) {
                y1 = y + 0.5 ;
            } else {
                y1 = y ;
            }
            gc.moveTo(0, y1);
            gc.lineTo(width, y1);
            gc.stroke();
        }
        return canvas ;
    }

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

и результаты:

enter image description here