Как нарисовать линию 1 пикселя с помощью JavaFX Canvas?
я гуглил и искал, нашел некоторые связанные вопросы / сообщения, но ни один из адресов моей проблемы.
Я рисую линии непосредственно на холсте (JavaFX), используя:
gc.setStroke(color);
gc.setLineWidth(lineWidth);
gc.strokeLine(startX, startY, endX, endY);
Я хочу линии ширины 1 пиксела. Поэтому я установил lineWidth=1. Я понимаю.:
обратите внимание, что линии размыты. Это не 1 пиксель. Я пытался установить ширину линии до 0,1 или 0,01 и т. д. Результат не меняется.
кстати... Я не понимаю, почему этот параметр является двойным. Я где-то читал, что это связано с DPI. Но я не понимаю, что такое единица измерения и как она преобразуется в пиксели. Документация Oracle не помогает. (или я не нашел тот, который помогает)
Я хотел бы получить это вместо этого:
Это было реализовано на другой платформе. Обратите внимание, что линии и всего в 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);
}
}
и результаты: