您的位置:首页 > 编程语言 > Java开发

javaFX初探(使用画布 API)

2015-01-26 18:06 881 查看
本章介绍javaFX画布API的使用。

概述

javaFX 画布API提供了自定义的纹理。画布API有两个主要的类,Canvas 和 GraphicsContext,定义在javafx.scene.canvas包下。我们可

以创建一个Canvas对象,燃火获得它的GraphicsContext,然后渲染我们自定义的形状。因为Canvas是Node的子类,所以我们可以在场景图

中使用。

基本形状:

下面这个例子使用 Canvas和GraphicesContext来画出圆,矩形,多边形等。代码如下:

package com.chu.canvas;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
 
public class BasicOpsTest extends Application {
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Drawing Operations Test");
        Group root = new Group();
        Canvas canvas = new Canvas(300, 250);
        GraphicsContext gc = canvas.getGraphicsContext2D();
       
        drawShapes(gc);
        
        root.getChildren().add(canvas);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private void drawShapes(GraphicsContext gc) {
        gc.setFill(Color.GREEN);
        gc.setStroke(Color.BLUE);
        gc.setLineWidth(5);
        gc.strokeLine(40, 10, 10, 40);
        gc.fillOval(10, 60, 30, 30);
        gc.strokeOval(60, 60, 30, 30);
        gc.fillRoundRect(110, 60, 30, 30, 10, 10);
        gc.strokeRoundRect(160, 60, 30, 30, 10, 10);
        gc.fillArc(10, 110, 30, 30, 45, 240, ArcType.OPEN);
        gc.fillArc(60, 110, 30, 30, 45, 240, ArcType.CHORD);
        gc.fillArc(110, 110, 30, 30, 45, 240, ArcType.ROUND);
        gc.strokeArc(10, 160, 30, 30, 45, 240, ArcType.OPEN);
        gc.strokeArc(60, 160, 30, 30, 45, 240, ArcType.CHORD);
        gc.strokeArc(110, 160, 30, 30, 45, 240, ArcType.ROUND);
        gc.fillPolygon(new double[]{10, 40, 10, 40},
                       new double[]{210, 210, 240, 240}, 4);
        gc.strokePolygon(new double[]{60, 90, 60, 90},
                         new double[]{210, 210, 240, 240}, 4);
        gc.strokePolyline(new double[]{110, 140, 110, 140},
                          new double[]{210, 210, 240, 240}, 4);
    }
}

运行如下图所示:


]

使用渐变和阴影]

这个例子使用了更多的GraphicsContext的方法,比如:strokeLine, fillOval, strokeArc, 和fillPolygon

代码如下:

package com.chu.canvas;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.DropShadow;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.stage.Stage;

public class CanvasTest extends Application {

    private Canvas canvas = new Canvas(200, 200);
    private GraphicsContext gc = canvas.getGraphicsContext2D();
    private Group root = new Group();

    @Override
    public void start(Stage primaryStage) {
              //  setUserAgentStylesheet(STYLESHEET_MODENA);
        primaryStage.setTitle("Canvas Test");
        moveCanvas(0,0);
        drawDShape();
        drawRadialGradient(Color.RED, Color.YELLOW);
        drawLinearGradient(Color.BLUE, Color.GREEN);
        drawDropShadow(Color.GRAY, Color.BLUE, Color.GREEN, Color.RED);
        root.getChildren().add(canvas);
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }

    /**
     * Moves the canvas to a new location within the Scene. This is accomplished
     * by performing a translation transformation on the Canvas object, passing 
     * in the desired x and y coordinates. Passing in values of 0,0 will position
     * the Canvas in the upper left corner of the Scene.
     * @param x The new x coordinate
     * @param y The new y coordinate
     */
    private void moveCanvas(int x, int y) {
        canvas.setTranslateX(x);
        canvas.setTranslateY(y);
    }

    /**
     * Draws an area in the shape of a capital letter "D."
     * The user can try substituting numbers 
     * of their own in the bezierCurveTo parameters to 
     * warp the shape away from the letter "D."
     */
    private void drawDShape() {
        gc.beginPath();
        gc.moveTo(50, 50);
        gc.bezierCurveTo(150, 20, 150, 150, 75, 150);
        gc.closePath();
    }

    /**
     * Draws a radial gradient on the Canvas object, which appears as a series of
     * circles radiating outward. This demo uses RED and YELLOW by default. 
     * 
     * @param firstColor The color used in the first Stop of the gradient.
     * @param lastColor  The color used in the last Stop of the gradient.
     */
    private void drawRadialGradient(Color firstColor, Color lastColor) {
        gc.setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.1, true,
                CycleMethod.REFLECT,
                new Stop(0.0, firstColor),
                new Stop(1.0, lastColor)));
        gc.fill();
    }

    /**
     * Draws a linear gradient on the Canvas object, which colors the letter "D"
     * from top to bottom. The default colors used in this demo are BLUE and GREEN.
     * 
     * @param firstColor
     * @param secondColor 
     */
    private void drawLinearGradient(Color firstColor, Color secondColor) {
        LinearGradient lg = new LinearGradient(0, 0, 1, 1, true,
                CycleMethod.REFLECT,
                new Stop(0.0, firstColor),
                new Stop(1.0, secondColor));
        gc.setStroke(lg);
        gc.setLineWidth(20);
        gc.stroke();
    }

    /**
     * Draws a four separate drop shadows around the letter "D." The default 
     * colors used in the demo are GREY, BLUE, GREEN, and RED. 
     * 
     * @param firstColor
     * @param secondColor
     * @param thirdColor
     * @param fourthColor 
     */
    private void drawDropShadow(Color firstColor, Color secondColor,
            Color thirdColor, Color fourthColor) {
        gc.applyEffect(new DropShadow(20, 20, 0, firstColor));
        gc.applyEffect(new DropShadow(20, 0, 20, secondColor));
        gc.applyEffect(new DropShadow(20, -20, 0, thirdColor));
        gc.applyEffect(new DropShadow(20, 0, -20, fourthColor));
    }
        
    public static void main(String[] args) {
        launch(args);
    }
    
}

运行如下图所示:



用户交互

下面的例子,显示了一个蓝色的矩形,用户拖动鼠标可以抹去蓝色,双击可以还原。

代码如下:

package com.chu.canvas;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class CanvasDoodleTest extends Application {

    /**
     * Resets the canvas to its original look by filling in a rectangle covering
     * its entire width and height. Color.BLUE is used in this demo.
     *
     * @param canvas The canvas to reset
     * @param color The color to fill
     */
    private void reset(Canvas canvas, Color color) {
        GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.setFill(color);
        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Canvas Doodle Test");
        Group root = new Group();
        
        // Draw background with gradient
        Rectangle rect = new Rectangle(400, 400);
        drawBackground(rect);
        root.getChildren().add(rect);

        // Create the Canvas, filled in with Blue
        final Canvas canvas = new Canvas(200, 200);
        canvas.setTranslateX(100);
        canvas.setTranslateY(100);
        reset(canvas, Color.BLUE);
        
        final GraphicsContext gc = canvas.getGraphicsContext2D();
        
        // Clear away portions as the user drags the mouse
        canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {
                gc.clearRect(e.getX() - 2, e.getY() - 2, 5, 5);
            }
        });

        // Fill the Canvas with a Blue rectnagle when the user double-clicks
        canvas.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent t) {            
                if (t.getClickCount() >1) {
                    reset(canvas, Color.BLUE);
                }  
            }
        });

        // Add the Canvas to the Scene, and show the Stage
        root.getChildren().add(canvas);
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }

    /**
     * Draws the background with a RadialGradient 
     * that transitions from Red to Yellow.
     * @param rect the Rectangle to draw on the Canvas 
     */
    private void drawBackground(Rectangle rect) {
        rect.setFill(new LinearGradient(0, 0, 1, 1, true,
                CycleMethod.REFLECT,
                new Stop(0, Color.RED),
                new Stop(1, Color.YELLOW)));
    }
    
    public static void main(String[] args) {
        launch(args);
    }
    
}


运行如下图所示:



创建一个简单的系统层

我们可以创建多个Canvas对象,使用这个对象定义一个系统层。改变层后可以画不同的东西在画布上。

代码如下:

package com.chu.canvas;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.control.ChoiceBox;
import javafx.collections.FXCollections;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;

public class LayerTest extends Application {

	private Group root;
	private BorderPane borderPane;
	private Canvas layer1;
	private Canvas layer2;
	private GraphicsContext gc1;
	private GraphicsContext gc2;
	private ChoiceBox cb;

	private void createLayers() {

		// Layers 1&2 are the same size
		layer1 = new Canvas(300, 250);
		layer2 = new Canvas(300, 250);

		// Obtain Graphics Contexts
		gc1 = layer1.getGraphicsContext2D();
		gc1.setFill(Color.GREEN);
		gc1.fillOval(50, 50, 20, 20);
		gc2 = layer2.getGraphicsContext2D();
		gc2.setFill(Color.BLUE);
		gc2.fillOval(100, 100, 20, 20);
	}

	private void handleLayers() {
		// Handler for Layer 1
		layer1.addEventHandler(MouseEvent.MOUSE_PRESSED,
				new EventHandler<MouseEvent>() {
					@Override
					public void handle(MouseEvent e) {
						gc1.fillOval(e.getX(), e.getY(), 20, 20);
					}
				});

		// Handler for Layer 2
		layer2.addEventHandler(MouseEvent.MOUSE_PRESSED,
				new EventHandler<MouseEvent>() {
					@Override
					public void handle(MouseEvent e) {
						gc2.fillOval(e.getX(), e.getY(), 20, 20);
					}
				});
	}

	private void createChoiceBox() {
		cb = new ChoiceBox();
		cb.setItems(FXCollections.observableArrayList("Layer 1 is GREEN",
				"Layer 2 is BLUE"));
		cb.getSelectionModel().selectedItemProperty()
				.addListener(new ChangeListener() {
					@Override
					public void changed(ObservableValue o, Object o1, Object o2) {
						if (o2.toString().equals("Layer 1 is GREEN")) {
							layer1.toFront();
						} else if (o2.toString().equals("Layer 2 is BLUE")) {
							layer2.toFront();
						}
					}
				});
		cb.setValue("Layer 1 is GREEN");
	}

	private void addLayers() {
		// Add Layers
		borderPane.setTop(cb);
		Pane pane = new Pane();
		pane.getChildren().add(layer1);
		pane.getChildren().add(layer2);
		layer1.toFront();
		borderPane.setCenter(pane);
		root.getChildren().add(borderPane);
	}

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

	@Override
	public void start(Stage primaryStage) {

		// Build GUI
		borderPane = new BorderPane();
		primaryStage.setTitle("Layer Test");
		root = new Group();
		createLayers();
		handleLayers();
		createChoiceBox();
		addLayers();

		// Show Scene
		primaryStage.setScene(new Scene(root));
		primaryStage.show();
	}
}


运行代码如下图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: