While working on FlexGanttFX I had to deal a lot with the JavaFX Canvas node. I am using it to render activities on a timeline. Each row in the Gantt chart is a Canvas node. The user has the option to resize each row individually. So I had to figure out the best way to resize a canvas, which out-of-the-box is not resizable. The listing below shows how this can be accomplished.

The main steps needed are:

  • Create a subclass of Canvas.
  • Override the isResizable() method and return true.
  • Override the prefWidth() and prefHeight() methods. Return the values of Canvas.getWidth() and Canvas.getHeight().
  • Add listeners to the width and height properties of Canvas in order to trigger a redraw when the size of the canvas changes.
  • Bind the width and height properties of Canvas to the width and height properties of the parent pane.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
 
/**
 * Tip 1: A canvas resizing itself to the size of
 *        the parent pane.
 */
public class Tip1ResizableCanvas extends Application {
 
  class ResizableCanvas extends Canvas {
 
    public ResizableCanvas() {
      // Redraw canvas when size changes.
      widthProperty().addListener(evt -> draw());
      heightProperty().addListener(evt -> draw());
    }
 
    private void draw() {
      double width = getWidth();
      double height = getHeight();
 
      GraphicsContext gc = getGraphicsContext2D();
      gc.clearRect(0, 0, width, height);
 
      gc.setStroke(Color.RED);
      gc.strokeLine(0, 0, width, height);
      gc.strokeLine(0, height, width, 0);
    }
 
    @Override
    public boolean isResizable() {
      return true;
    }
 
    @Override
    public double prefWidth(double height) {
      return getWidth();
    }
 
    @Override
    public double prefHeight(double width) {
      return getHeight();
    }
  }
 
  @Override
  public void start(Stage stage) throws Exception {
    ResizableCanvas canvas = new ResizableCanvas();
 
    StackPane stackPane = new StackPane();
    stackPane.getChildren().add(canvas);
 
    // Bind canvas size to stack pane size.
    canvas.widthProperty().bind(
                       stackPane.widthProperty());
    canvas.heightProperty().bind(
                       stackPane.heightProperty());
 
    stage.setScene(new Scene(stackPane));
    stage.setTitle("Tip 1: Resizable Canvas");
    stage.show();
  }
 
  public static void main(String[] args) {
    launch(args);
  }
}

When run you should see the following:
Bildschirmfoto 2014-04-10 um 11.30.31