JavaFX Tip 1: Resizable Canvas

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

About these ads
Tagged

9 thoughts on “JavaFX Tip 1: Resizable Canvas

  1. […] posts this week, both of which are tips for fellow JavaFX developers. Firstly, he has posted about creating a resizable canvas in JavaFX, and secondly he has posted a tip about how to ensure lines are sharp / non-blurry when […]

  2. […] posts this week, both of which are tips for fellow JavaFX developers. Firstly, he has posted about creating a resizable canvas in JavaFX, and secondly he has posted a tip about how to ensure lines are sharp / non-blurry when […]

  3. reportmill says:

    Nice blog! I wasn’t really aware of the isResizable method – recently I overrode StackPane.layoutChildren() to manually resize a child canvas, and I didn’t quite stop to think about why I had to do that.

  4. dlemmermann says:

    If you do it that way then I think you will notice a little bit of a delay before the canvas content (the rendering / drawing) is actually updated.

  5. Ricardo Cruz says:

    That was of great help, thanks ! ;)

  6. Chris says:

    How I can create form with ResizableCanvas from fxml file?

  7. dlemmermann says:

    If you use SceneBuilder you will need to import a JAR file that contains the resizable canvas control.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Pixel Perfect

Where pixels have a home

Tomsondev Blog

Tom's opensource development

Carl's FX Blog

Just Ordinary Users of the API

Jasper Potts's Blog

Jasper Potts's Blog on Java and Life

Jasper Potts's Blog

Where pixels have a home

Exploding Pixels

Exposing the pixels behind beautiful user interfaces

Follow

Get every new post delivered to your Inbox.

Join 25 other followers

%d bloggers like this: