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:
Reference: | JavaFX Tip 1: Resizable Canvas from our JCG partner Dirk Lemmermann at the Pixel Perfect blog. |