javaFX初探(使用画布 API)
2015-01-26 18:06
881 查看
本章介绍javaFX画布API的使用。
以创建一个Canvas对象,燃火获得它的GraphicsContext,然后渲染我们自定义的形状。因为Canvas是Node的子类,所以我们可以在场景图
中使用。
基本形状:
下面这个例子使用 Canvas和GraphicesContext来画出圆,矩形,多边形等。代码如下:
运行如下图所示:
]
代码如下:
运行如下图所示:
代码如下:
运行如下图所示:
代码如下:
运行代码如下图所示:
概述
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(); } }
运行代码如下图所示:
相关文章推荐
- javaFX初探(使用Image Ops API)
- Symbian学习笔记(19) - 初探Web Services API 的使用(下)
- Symbian学习笔记(17) - 初探WebServices API的使用(上)
- ArcGIS API for JavaScript开发初探——基本地图组件使用
- JavaFX使用摄像头API的示例
- HTML5画布元素canvas提供的API使用方法
- 04:一文初探Tensorflow高级API使用(初学者篇)
- Symbian学习笔记(18) - 初探Web Services API 的使用(中)
- HTML5实现页面切换激活的PageVisibility API使用初探
- 深入探讨JavaMail API的使用
- 使用PB调用API自动更新(非FTP模式)(一、STRUCTURE定义)
- 面向对象的Windows编程实战(上)(使用C++和Win32 API)
- 使用PB调用API自动更新(非FTP模式)(五、复制函数F_CONNECT_COPYFILE)
- 如何在VC++中使用API直接打印
- 在win32 api程序中:使用C++风格的字符串
- 使用PB调用API自动更新(非FTP模式)(六、AUTODOWN.INI文件)
- C#中使用正则表达式初探(10月21日首发)
- 使用PB调用API自动更新(非FTP模式)(二、API说明及定义(2))
- 使用PB调用API自动更新(非FTP模式)(四、统计复制文件数量函数F_CONNECT_COPYCOUNT)
- 使用API创建窗体(类似VC的创建过程)