Mikey Mikey - 24 days ago 24
Java Question

canvas is blank after drawImage()

I have a drawing window that allows a user to open an image, draw on it, then save it.

I have it on a canvas, and I can create a blank canvas, draw on it, and save it with no issues. But then when I try to open that image and do:

GraphicsContext gc = canvas.getGraphicsContext2D();
File file = new File(path);
Image img = new Image(file.toURI().toString());
gc.drawImage(img,0,0);


It does the same thing as before. I get a blank canvas, that image never shows up.

Did I do something wrong in the code? I know the path is correct because I can see that image in the thumbnail in other parts of the program.

UPDATE



Here is a complete sample program

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class GUITest extends Application{

String path = "10-9-2016-22-28.png";

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

@Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Canvas canvas = new Canvas(600,800);

GraphicsContext gc = canvas.getGraphicsContext2D();
Image original = new Image(getClass().getResourceAsStream(path));
gc.drawImage(original, 0, 0);

root.getChildren().add(canvas);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
}


It works now until I do
canvas.widthProperty().bind(root.widthProperty());
and
canvas.heightProperty().bind(root.heightProperty());
. Is there something wrong with binding canvas dimensions with it's parent's dimensions?

Answer

The size of a Pane becomes non-0 when the first layout pass is executed. Before the size is (0, 0). Since there is no room in a canvas of size (0, 0) all the content is removed. Later when the Canvas grows to the root's size, you do not redraw the image, therefore nothing is shown.

For this reason every time the Canvas is resized you need to draw the canvas content again (or at least until the size becomes non-zero).

For the same reason you need to set the prefered size of the scene at the root element, not by setting the Canvas size.

@Override
public void start(Stage primaryStage) throws Exception {
    Pane root = new Pane();
    root.setPrefSize(600, 800);
    Canvas canvas = new Canvas();

    GraphicsContext gc = canvas.getGraphicsContext2D();
    Image original = new Image(getClass().getResourceAsStream(path));

    root.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
        canvas.setWidth(newValue.getWidth());
        canvas.setHeight(newValue.getHeight());
        gc.drawImage(original, 0, 0);
    });

    root.getChildren().add(canvas);
    Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.show();
}
Comments