We are using javafx to develop a scalable graphics program. Considering the performance, we use javafx canvas to draw a lot of rectangular boxes. The rectangular box represents the position of the container. We found that the rectangle will appear thick and thin lines, blurred and so on. Our graphics need to be scaled. The calculated width and coordinates of the rectangular frame will have floating point numbers. We can't solve the problem by using the following post. How to draw a crisp, opaque hairline in JavaFX 2.2?
This is my example.
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class LineScaleTest extends Application {
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) {
AnchorPane anchorPane=new AnchorPane();
Canvas canvas=new Canvas(500,300);
canvas.relocate(300,300);
GraphicsContext gc=canvas.getGraphicsContext2D();
for(int i=0;i<10;i++){
gc.strokeRoundRect(10.5+35*i,5.5,30,30,0,0);
}
for(int i=0;i<10;i++){
gc.strokeRoundRect(10.5+35*i,65.5,30,30,0,0);
}
for(int i=0;i<10;i++){
gc.strokeRoundRect(10.5+35*i,115.5,30,30,0,0);
}
anchorPane.setOnScroll(new EventHandler<ScrollEvent>() {
@Override
public void handle(ScrollEvent e) {
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor = (e.getDeltaY() > 0) ? 1.1
: 1 / 1.1;
anchorPane.setScaleX(anchorPane.getScaleX() * scaleFactor);
anchorPane.setScaleY(anchorPane.getScaleY() * scaleFactor);
}
});
anchorPane.getChildren().add(canvas);
Scene scene = new Scene( anchorPane,1200, 700);
stage.setScene(scene);
stage.show();
}
}
example2#############################################################
public class LineScaleTest extends Application { public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) {
AnchorPane anchorPane=new AnchorPane();
Canvas canvas=new Canvas(500,300);
canvas.relocate(300,300);
GraphicsContext gc=canvas.getGraphicsContext2D();
for(int i=0;i<10;i++){
gc.strokeRoundRect(10.5+35*i,5.5,30,30,0,0);
}
for(int i=0;i<10;i++){
gc.strokeRoundRect(10.5+35*i,65.5,30,30,0,0);
}
for(int i=0;i<10;i++){
gc.strokeRoundRect(10.5+35*i,115.5,30,30,0,0);
}
anchorPane.setOnScroll(new EventHandler<ScrollEvent>() {
@Override
public void handle(ScrollEvent e) {
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor = (e.getDeltaY() > 0) ? 1.1
: 1 / 1.1;
Scale scale=new Scale(anchorPane.getScaleX() * scaleFactor,anchorPane.getScaleY() * scaleFactor);
Affine reflectTransform = new Affine();
reflectTransform.append(scale);
canvas.getTransforms().add(reflectTransform);
}
});
anchorPane.getChildren().add(canvas);
Scene scene = new Scene( anchorPane,1200, 700);
stage.setScene(scene);
stage.show();
}
}
Instead of scaling the anchorPane you can define a affine transformation for the Canvas. The GraphicsContext provides functionality to do so.
I don't think you can rely on anything built into JavaFX to produce exactly the result you want. Your application will need to manage this itself in order to produce the desired result. So instead of calling "scale" you will need to increase the canvas width and height yourself and then perform a redrawing based on the new dimensions. Your rendering code can then ensure that the coordinates used will not cause fuzziness or blur.