/*
 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javafx.scene.canvas;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.DoublePropertyBase;
import javafx.geometry.NodeOrientation;
import javafx.scene.Node;
import com.sun.javafx.geom.BaseBounds;
import com.sun.javafx.geom.RectBounds;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.scene.DirtyBits;
import com.sun.javafx.scene.NodeHelper;
import com.sun.javafx.scene.canvas.CanvasHelper;
import com.sun.javafx.sg.prism.GrowableDataBuffer;
import com.sun.javafx.sg.prism.NGCanvas;
import com.sun.javafx.sg.prism.NGNode;

Canvas is an image that can be drawn on using a set of graphics commands provided by a GraphicsContext.

A Canvas node is constructed with a width and height that specifies the size of the image into which the canvas drawing commands are rendered. All drawing operations are clipped to the bounds of that image.

Example:

import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.canvas.*;
Group root = new Group();
Scene s = new Scene(root, 300, 300, Color.BLACK);
final Canvas canvas = new Canvas(250,250);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.BLUE);
gc.fillRect(75,75,100,100);
root.getChildren().add(canvas);
See Also:
Since:JavaFX 2.2
/** * {@code Canvas} is an image that can be drawn on using a set of graphics * commands provided by a {@link GraphicsContext}. * * <p> * A {@code Canvas} node is constructed with a width and height that specifies the size * of the image into which the canvas drawing commands are rendered. All drawing * operations are clipped to the bounds of that image. * </p> * * <p>Example:</p> * * <pre> import javafx.scene.*; import javafx.scene.paint.*; import javafx.scene.canvas.*; Group root = new Group(); Scene s = new Scene(root, 300, 300, Color.BLACK); final Canvas canvas = new Canvas(250,250); GraphicsContext gc = canvas.getGraphicsContext2D(); gc.setFill(Color.BLUE); gc.fillRect(75,75,100,100); root.getChildren().add(canvas); * </pre> * * @see GraphicsContext * @since JavaFX 2.2 */
public class Canvas extends Node { static { CanvasHelper.setCanvasAccessor(new CanvasHelper.CanvasAccessor() { @Override public NGNode doCreatePeer(Node node) { return ((Canvas) node).doCreatePeer(); } @Override public void doUpdatePeer(Node node) { ((Canvas) node).doUpdatePeer(); } @Override public BaseBounds doComputeGeomBounds(Node node, BaseBounds bounds, BaseTransform tx) { return ((Canvas) node).doComputeGeomBounds(bounds, tx); } @Override public boolean doComputeContains(Node node, double localX, double localY) { return ((Canvas) node).doComputeContains(localX, localY); } }); } static final int DEFAULT_VAL_BUF_SIZE = 1024; static final int DEFAULT_OBJ_BUF_SIZE = 32; private static final int SIZE_HISTORY = 5; private GrowableDataBuffer current; private boolean rendererBehind; private int recentvalsizes[]; private int recentobjsizes[]; private int lastsizeindex; private GraphicsContext theContext; { // To initialize the class helper at the begining each constructor of this class CanvasHelper.initHelper(this); }
Creates an empty instance of Canvas.
/** * Creates an empty instance of Canvas. */
public Canvas() { this(0, 0); }
Creates a new instance of Canvas with the given size.
Params:
  • width – width of the canvas
  • height – height of the canvas
/** * Creates a new instance of Canvas with the given size. * * @param width width of the canvas * @param height height of the canvas */
public Canvas(double width, double height) { this.recentvalsizes = new int[SIZE_HISTORY]; this.recentobjsizes = new int[SIZE_HISTORY]; setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT); setWidth(width); setHeight(height); } private static int max(int sizes[], int defsize) { for (int s : sizes) { if (defsize < s) defsize = s; } return defsize; } GrowableDataBuffer getBuffer() { NodeHelper.markDirty(this, DirtyBits.NODE_CONTENTS); NodeHelper.markDirty(this, DirtyBits.NODE_FORCE_SYNC); if (current == null) { int vsize = max(recentvalsizes, DEFAULT_VAL_BUF_SIZE); int osize = max(recentobjsizes, DEFAULT_OBJ_BUF_SIZE); current = GrowableDataBuffer.getBuffer(vsize, osize); theContext.updateDimensions(); } return current; } boolean isRendererFallingBehind() { return rendererBehind; }
returns the GraphicsContext associated with this Canvas.
Returns:the GraphicsContext associated with this Canvas
/** * returns the {@code GraphicsContext} associated with this {@code Canvas}. * @return the {@code GraphicsContext} associated with this {@code Canvas} */
public GraphicsContext getGraphicsContext2D() { if (theContext == null) { theContext = new GraphicsContext(this); } return theContext; }
Defines the width of the canvas.
@defaultValue0.0
/** * Defines the width of the canvas. * * @defaultValue 0.0 */
private DoubleProperty width; public final void setWidth(double value) { widthProperty().set(value); } public final double getWidth() { return width == null ? 0.0 : width.get(); } public final DoubleProperty widthProperty() { if (width == null) { width = new DoublePropertyBase() { @Override public void invalidated() { NodeHelper.markDirty(Canvas.this, DirtyBits.NODE_GEOMETRY); NodeHelper.geomChanged(Canvas.this); if (theContext != null) { theContext.updateDimensions(); } } @Override public Object getBean() { return Canvas.this; } @Override public String getName() { return "width"; } }; } return width; }
Defines the height of the canvas.
@defaultValue0.0
/** * Defines the height of the canvas. * * @defaultValue 0.0 */
private DoubleProperty height; public final void setHeight(double value) { heightProperty().set(value); } public final double getHeight() { return height == null ? 0.0 : height.get(); } public final DoubleProperty heightProperty() { if (height == null) { height = new DoublePropertyBase() { @Override public void invalidated() { NodeHelper.markDirty(Canvas.this, DirtyBits.NODE_GEOMETRY); NodeHelper.geomChanged(Canvas.this); if (theContext != null) { theContext.updateDimensions(); } } @Override public Object getBean() { return Canvas.this; } @Override public String getName() { return "height"; } }; } return height; } private NGNode doCreatePeer() { return new NGCanvas(); } /* * Note: This method MUST only be called via its accessor method. */ private void doUpdatePeer() { if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) { NGCanvas peer = NodeHelper.getPeer(this); peer.updateBounds((float)getWidth(), (float)getHeight()); } if (NodeHelper.isDirty(this, DirtyBits.NODE_CONTENTS)) { NGCanvas peer = NodeHelper.getPeer(this); if (current != null && !current.isEmpty()) { if (--lastsizeindex < 0) { lastsizeindex = SIZE_HISTORY - 1; } recentvalsizes[lastsizeindex] = current.writeValuePosition(); recentobjsizes[lastsizeindex] = current.writeObjectPosition(); rendererBehind = peer.updateRendering(current); current = null; } } } /* * Note: This method MUST only be called via its accessor method. */ private boolean doComputeContains(double localX, double localY) { double w = getWidth(); double h = getHeight(); return (w > 0 && h > 0 && localX >= 0 && localY >= 0 && localX < w && localY < h); } /* * Note: This method MUST only be called via its accessor method. */ private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) { bounds = new RectBounds(0f, 0f, (float) getWidth(), (float) getHeight()); bounds = tx.transform(bounds, bounds); return bounds; } }