zoukankan      html  css  js  c++  java
  • Qt Quick之Canvas

      QML中的Canvas,俗称画布,它用来定义一个绘图区域,可以使用ECMAScript代码来绘制直线,矩形,贝塞尔曲线,弧线,图片,文字等图元,还可以为这些图元应用填充颜色和边框颜色,甚至还可以进行低阶的像素级的操作。

    1. 几个重要概念

    (1)画布

      下面的代码定义了一个宽320像素高240像素的画布

    Canvas
    {
        320;
        height:240;
    }

    (2)画师

      画师如同MFC中的DC和Qt C++中的QPainter,那么QML中的画师是谁呢?Content2D是也!可以在Qt帮助文档中使用索引模式查找“Context2D”关键字来查看相关信息。

      方法1: 

    Canvas
    {
        onPaint:    
        {
            var ctx = getContext("2d");
        }
    }

      方法2:

    Canvas{
        id:canvas;
        contextType:"2d";
    
        onPaint:{
            context.lineWidth=2;
        }
    }

    (3)画笔

      lineWidth:设置画笔的宽度

      strokeStyle:设置画笔颜色或风格

    (4)画刷

      在context2D这里,fillStyle属性是描述画刷的

    (5)坐标系

      (0,0)为左上角,x轴水平向右为正,y轴垂直向下为正

    (6)图元

      基本图元有线,弧,矩形,曲线,文本,图片等

    2. 基本绘图模式

     Canvas
        {
            400;
            height:240;
            onPaint:
            {
                var ctx = getContext("2d");
    
                ctx.lineWidth = 2;  // 设置画笔宽度
                ctx.strockStyle="red"; // 设置画笔颜色
                ctx.fillStyle="blue"; // 设置填充色
    
                ctx.beginPath();
                ctx.rect(100,80,120,80);
                ctx.fill();
                ctx.stroke();
            }
        }

      上面代码演示如何绘制一个矩形和矩形边框,展示了使用Canvas和Context2D绘图的一般步骤:

    (1)定义一个Canvas对象,设置width和Height

    (2)定义onPaint信号处理器

    (3)获取Context2D对象

    (4)实际的绘图操作

    3. 绘制路径

      使用Content2D绘制路径的一般步骤:

    (1)调用beginPath()

    (2)调用moveTo(),lineTo(),rect(),quadraticCurveTo(),arc(),bezierCurveTo()等可以构造路径元素的方法

    (3)调用fill()或stroke()

      这里主要介绍下fillStyle属性的使用,fillStyle与Qt C++中的QBrush类似,保存用于填充图元的画刷,它可以是一个颜色值,也可以是CanvasGradient或CanvasPattern对象

    Canvas
        {
             400;
            height: 240;
            contextType:"2d";
            onPaint:
            {
                var ctx = getContext("2d");
                ctx.lineWidth = 2;
                ctx.lineJoin = "round"
                ctx.strokeStyle = "red";
                ctx.font = "42px sans-serif";
    
                //ctx.fillStyle = "blue"; // 使用颜色进行填充
                var gradient = ctx.createLinearGradient(100,80,220,160);
                gradient.addColorStop(0, Qt.rgba(255,255,255,1));
                gradient.addColorStop(1, Qt.rgba(0,0,0,1));
                ctx.fillStyle =gradient; // 使用渐变对象进行填充
    
                ctx.beginPath();
                ctx.moveTo(240,80);
                ctx.lineTo(300,90);
                ctx.rect(100,80,250,150);
                ctx.text("stroke text", 110,120);
                ctx.fill();
    
                ctx.stroke();
            }
        }

      注意:closePath()方法用于结束当前的路径,从路径终点到起点绘制一条直线来封闭路径,比如:

    ctx.beginPath();
    ctx.moveTo(100,80);
    ctx.lineTo(100,200);
    ctx.lineTo(300,200);
    ctx.closePath();
    ctx.fill();
    ctx.stroke();

      通过closePath绘制一个三角形

    4. 绘制文本

    Context2D对象与文本相关的方法有三个:fillText(),strokeText(),text()

    fillText()使用fillStyle填充文字

    strokeTexr()使用strokeStyle描文字边框

    text()方法在路径上添加一串文本作为构成路径的元素之一

    上面代码效果:

    5. 绘制图片

      Context2D有4种不同形式的drawImage()方法,可以用来绘制图片

    (1)显示本地图片

    (2)显示网络图片

    Canvas
        {
             600;
            height: 600;
            id:canvas;
            property var imageName: "dartlike_weapon.png";
            property var imageUrl: "http://g2.ykimg.com/0516000053548ED267379F510C0061FA";
    
            onPaint:
            {
                var ctx = getContext("2d");
    
                ctx.drawImage(imageUrl, 200,0); // 绘制网络图片
    
                ctx.drawImage(imageName, 0,200);   // 绘制本地图片
            }
    
            Component.onCompleted:
            {
                loadImage(imageUrl);  // 异步加载图片,图片加载完发射imageLoaded信号
                loadImage(imageName);
            }
    
            onImageLoaded:
            {
                requestPaint();  // 重绘Canvas
            }
        }

      上面的代码演示了显示本地和网络图片,Component.onCompleted附加信号处理器内调用Canvas的loadImage()方法来加载图片,该方法会异步加载图片,当图片加载完成时,发射imageLoaded信号,在对应的信号处理器onImageLoaded内调用requestPainte()方法来重回Canvas.怎样知道图片是否加载成功了呢?可以通过Canvas的isImageError(),isImageLoaded()两个方法来判断,他们接受和loadImage()同样的参数,返回布尔值,只有成功加载的图片才可以使用Context2D来绘制。

    (3)使用Image属性显示网络图片

        Image
            {
                id:imageSource;
                source: "http://g2.ykimg.com/0516000053548ED267379F510C0061FA";
                visible: false;
                onStateChanged: {
                    if(status == Image.Ready)
                    {
                        canvas.requestPaint();
                    }
                }
            }

    (4)使用createImageData显示图像

      drawImage还可以绘制CanvasImageData对象,CanvasImageData对象使用一维数组,按照RGBA的顺序来保存图像数据

        onPaint:
            {
                var ctx = getContext("2d");
    
                if(imageData == null)
                {
                    imageData = ctx.createImageData(120,100);
                    for (var i = 0;i < 48000;i+=4)
                    {
                        imageData.data[i] = Math.floor(Math.random()*255);
                        imageData.data[i+1] = Math.floor(Math.random()*255);
                        imageData.data[i+2] = Math.floor(Math.random()*255);
                        imageData.data[i+3] = 255;
                    }
                }
    
                ctx.drawImage(imageData,0,0);   // 绘制createImageData
            }

    (5)4种方法的综合实例

    import QtQuick 2.9
    import QtQuick.Window 2.2
    
    Window {
        visible: true
         800
        height: 600
        title: qsTr("Hello World")
    
        Canvas
        {
             600;
            height: 600;
            id:canvas;
            property var imageName: "dartlike_weapon.png";
            property var imageUrl: "http://g2.ykimg.com/0516000053548ED267379F510C0061FA";
    
            Image
            {
                id:imageSource;
                source: "http://g2.ykimg.com/0516000053548ED267379F510C0061FA";
                visible: false;
                /*onStateChanged: {
                    if(status == Image.Ready)
                    {
                        canvas.requestPaint();
                    }
                }*/
            }
    
            property var imageData: null;
            onPaint:
            {
                var ctx = getContext("2d");
    
                if(imageData == null)
                {
                    imageData = ctx.createImageData(120,100);
                    for (var i = 0;i < 48000;i+=4)
                    {
                        imageData.data[i] = Math.floor(Math.random()*255);
                        imageData.data[i+1] = Math.floor(Math.random()*255);
                        imageData.data[i+2] = Math.floor(Math.random()*255);
                        imageData.data[i+3] = 255;
                    }
                }
    
                ctx.drawImage(imageData,0,0);   // 绘制createImageData
                ctx.drawImage(imageUrl, 200,0); // 绘制网络图片
    
                ctx.drawImage(imageSource, 200,200); // 绘制image属性
                ctx.drawImage(imageName, 0,200);   // 绘制本地图片
            }
    
            Component.onCompleted:
            {
                loadImage(imageUrl);  // 异步加载图片,图片加载完发射imageLoaded信号
                loadImage(imageName);
                loadImage(imageSource);
            }
    
            onImageLoaded:
            {
                requestPaint();  // 重绘Canvas
            }
        }
    }
    View Code

  • 相关阅读:
    10个超实用的PHP代码片段
    MySQL支撑百万级流量高并发的网站部署详解
    程序员总结:帮助你早些明白一些道理
    50个最常用的UNIX / Linux命令(结合实例)
    php.ini 核心配置选项说明
    智能指针的死穴 循环引用
    滥用vector带来的瓶颈
    JS——层的遮罩效果
    【趣】无广告看视频
    【SQLServer】远程访问数据库进行配置
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/9803573.html
Copyright © 2011-2022 走看看