JavaFX之2D编程(Canvas)

简介

源码下载

2d编程实际开发中很常见,比如生成一个验证码,二维码,图片裁剪压缩什么的。在桌面应用中,自定控件的外观的渲染,都是通过2D图像接口来实现的。当然,我们也可以利用这些编程接口,做一个画图工具。JavaFX中专门提供一个Canvas的组件,用来画画。比如下图中,用代码画出来的一些几何图形:

Canvas提供了一个操作手柄,叫做GraphicsContext,可以通过Canvas的实例获得:

GraphicsContext gc = canvas.getGraphicsContext2D();

Canvas是一种自上而下的流式画图方式,每次画图之前,采用上文的设置,比如颜色,线条粗细等。同样画下一个图形前,先更改设置,再绘制下一个图形,如果不更改设置,则延用之前的设置。比如:

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);

Canvas中的图像设置

属性保存/还原默认值描述
常规属性
裁剪YesNo clipping各种裁剪路径的抗锯齿相交区域,渲染仅限于此区域内。
全局透明度Yes1.0一个不透明度值,用于控制每次渲染操作的可见度或淡入淡出效果。
全局混合模式YesSRC_OVER一个“混合模式”枚举值,用于控制每个渲染操作所产生的像素如何与现有图像进行合成。
变形YesIdentity一个 3x2 的二维仿射变换矩阵,用于控制坐标如何映射到画布图像的逻辑像素上。
特效Yesnull一种单独应用于每个渲染操作的效果。
填充属性
填充颜色YesBLACK在填充操作中,用于涂抹于图形内部的涂料。
Stroke Attributes
线条颜色YesBLACK在描边操作中,用于涂抹于图形边界上的颜料。
线宽Yes1.0在描边操作中,应用于形状边界处的描边宽度。
线帽YesSQUARE在一笔画操作中,应用于每个破折号及其/或子路径起始和结束处的端帽样式。
连接点YesMITER在描边操作中,用于连接形状边界路径中各个部分的连接方式。
斜角限制Yes10.0在形状边界路径的各段之间存在锐角拐弯处时,对于一条“MITER”线段连接在该锐角拐弯方向上的延伸距离(相对于线宽而言)的限制值,该限制值决定了在绘制操作中该连接线段是否会被截断为“BEVEL”连接形式。
虚线Yesnull在描边操作中,应用于形状边界各段的虚线长度数组。
虚线偏移量Yes0.0在绘制操作中,用于确定在形状边界上开始绘制分段图案时所对应的虚线长度数组偏移量的值。
文本属性
字体YesDefault Font用于所有填充和描边文本操作的字体。
文本对齐YesLEFT文本在与文本操作中指定的 X 坐标相对应的位置上的水平排列方式。
文本基线YesBASELINE文本相对于文本操作中指定的 Y 坐标的垂直位置。
字体平滑YesGRAY对于所有填充文本操作而言,该字体中用于字符平滑(即抗锯齿处理)的类型。
路径属性
曲线路径NoEmpty path通过多种路径构建方法所构建的路径,将用于各种路径填充、描边或裁剪操作。
填充规则YesNON_ZERO用于确定路径填充或裁剪操作中路径内部区域的方法。
图片属性
图片平滑Yestrue一个布尔型状态值,用于控制“drawImage”(所有形式)中图像的平滑效果的开启或关闭。

Canvas的画图接口

也就是GraphicsContext可调用的类方法:

方法名常规填充线框文本路径图片
基本形状
fillRect()fillRoundRect()fillOval()fillArc()YesYesNoNoNoNo
strokeLine()strokeRect()strokeRoundRect()strokeOval()strokeArc()YesNoYesNoNoNo
clearRect()Yes [1]NoNoNoNoNo
fillPolygon()YesYesNoNoYes [2]No
strokePolygon()strokePolyline()YesNoYesNoNoNo
[1] 只有变形,裁切,特效用于 clearRect()
[2] 只有填充规则用于fillPolygon(), 剩余路径不会改变。
文本
fillText()fillText(with maxWidth)YesYesNoYes [3]NoNo
strokeText()strokeText(with maxWidth)YesNoYesYes [3]NoNo
[3] 只有填充形式的文本才能用字体平滑
路径
beginPath()moveTo()lineTo()quadraticCurveTo()bezierCurveTo()arc()arcTo()appendSVGPath()closePath()rect()Yes [4]NoNoNoNoNo
fill()Yes [4]YesNoNoYesNo
stroke()Yes [4]NoYesNoYes [5]No
clip()NoNoNoNoYesNo
[4] 变形仅用于路径创建的时候
[5] 填充规则只用于 fill() 和clip()
图片
drawImage(all forms)YesNoNoNoNoYes
杂项
applyEffect()PixelWriter methodsNoNoNoNoNoNo

示例1-基本图形

   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);
    }
}

示例2-渐变和阴影

  /**
     * 在画布对象上绘制一个径向渐变效果,该效果表现为一系列向外辐射的圆圈。
     * 此示例默认使用红色和黄色。 
     * 
     * @param firstColor 渐变的第一段所使用的颜色。
     * @param lastColor  渐变的最后一段所使用的颜色。
     */
    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();
    }

    /**
     * 渐变的最后一段所使用的颜色。在画布对象上绘制一条线性渐变,从上到下为字母“D”着色。
     * 此演示中使用的默认颜色为蓝色和绿色。
     * 
     * @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();
    }

    /**
     * 在字母“D”周围绘制四个独立的阴影效果。演示中所使用的默认颜色为灰色、蓝色、绿色和红色。
     * 
     * @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));
    }

示例3-涂鸦

涂鸦前:

涂鸦后:

鼠标拖拽时,清除掉指针附近的颜色:

     canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, 
       new EventHandler<MouseEvent>() {
           @Override
           public void handle(MouseEvent e) {
               gc.clearRect(e.getX() - 2, e.getY() - 2, 5, 5);
           }
       });

示例4-图层

    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);
            }
        });
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值