Issue
I have to draw a sinus curve in a javafx canvas dot after dot and connect these. But as you can change the width of the line to it sometimes gets cut in width because the line is near the border. So is there a possibility to like make a padding or a border to avoid this? It would be possible to like manipulate the coordinates but tbh I dont want to do that as I think there should be a better solution. Picture of the canvas
EDIT:
This is the code example to reproduce it in a javafx project
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
Canvas c = new Canvas(715,495);
GraphicsContext gc = c.getGraphicsContext2D();
VBox v = new VBox();
Pane p = new Pane();
p.getChildren().add(c);
Button b1 = new Button("Draw Sinus at Canvas");
b1.setOnAction(e -> drawSinus(c, gc));
v.getChildren().addAll(b1, p);
Scene sc = new Scene(v);
stage.setScene(sc);
stage.setTitle("Drawing Lines - Dynamically at Runtime");
stage.show();
}
private void drawSinus(Canvas c, GraphicsContext gc) {
double height = c.getHeight();
double width = c.getWidth();
double multiplier = (2 * Math.PI)/width;
double x1 = 0;
double y1 = height/2;
double x2 = 1;
double y2 = 0;
int i = 0;
gc.setStroke(Color.BLACK);
gc.setLineWidth(10);
while(i < width) {
y2 = (height/2) - ((height/2) * Math.sin(x2 * multiplier));
gc.strokeLine(x1,y1,x2,y2);
x1 = x2;
y1 = y2;
x2++;
i++;
}
}
public static void main(String[] args) {
launch();
}
}
Solution
One way to add some padding around the area in which you're drawing, without changing the coordinates you use, is to add a transform to the graphics context. Basically, you first scale the drawing area to make it smaller by ratios (width-2*padding)/width
and (height-2*padding)/height
(so the actual drawing area is reduced by a size 2*padding
in each dimension). Then translate by padding
in each dimension. This looks like:
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
Canvas c = new Canvas(715,495);
GraphicsContext gc = c.getGraphicsContext2D();
VBox v = new VBox();
Pane p = new Pane();
p.getChildren().add(c);
Button b1 = new Button("Draw Sinus at Canvas");
b1.setOnAction(e -> drawSinus(c, gc, 10));
v.getChildren().addAll(b1, p);
Scene sc = new Scene(v);
stage.setScene(sc);
stage.setTitle("Drawing Lines - Dynamically at Runtime");
stage.show();
}
private void drawSinus(Canvas c, GraphicsContext gc, double padding) {
double height = c.getHeight();
double width = c.getWidth();
Affine transform = new Affine(Transform.scale((width-2*padding)/width, (height-2*padding)/height));
transform.appendTranslation(padding, padding);
gc.setTransform(transform);
double multiplier = (2 * Math.PI)/width;
double x1 = 0;
double y1 = height/2;
double x2 = 1;
double y2 = 0;
int i = 0;
gc.setStroke(Color.BLACK);
gc.setLineWidth(10);
while(i < width) {
y2 = (height/2) - ((height/2) * Math.sin(x2 * multiplier));
gc.strokeLine(x1,y1,x2,y2);
x1 = x2;
y1 = y2;
x2++;
i++;
}
// reset transform; may not be necessary depending on actual use case
gc.setTransform(new Affine());
}
public static void main(String[] args) {
launch();
}
}
You need to reset the transform if you want to, e.g., clear the entire canvas, including the padded area.
Answered By - James_D
Answer Checked By - Timothy Miller (JavaFixing Admin)