IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> QML进阶(四)-绘制自定义控件 -> 正文阅读

[JavaScript知识库]QML进阶(四)-绘制自定义控件

在Qt中我们通过paintEvent和QPainter的组合可以在控件中进行各种绘制操作, 包括绘制各种图形和文字。同样在QML中引入了画布元素(canvas element),通过使用画布元素我们也可以画出各种各样的图形,同时这个元素允许脚本绘制。画布元素提供了一个依赖于分辨率的位图画布,你可以使用JavaScript脚本来绘制图形,制作游戏或者其它的动态图像。QML中的画布元素是基于HTML5的画布元素来完成的。

画布元素的基本思想是使用一个2D对象来渲染路径。这个2D对象包括了必要的绘图函数,画布元素充当绘制的画布。

下面分几类使用场景来介绍QML的画布元素的使用。

绘制基本元素

基本元素包括矩形、圆弧、圆角矩形、贝塞尔曲线、文本、渐变色、阴影效果、图片。

在Canvas控件中我们通过getContext("2d")接口可以获得绘制的上下文来进行绘制。

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("QML Canvas")

    Canvas{
           id: root
           width: 600; height: 600
           onPaint: {
               var ctx = getContext("2d")

               ctx.lineWidth = 3            //画笔的宽度
               ctx.strokeStyle = "#0000FF"  //画笔的颜色
               ctx.fillStyle = "#4D9CF8"    //填充的颜色

               /******绘制矩形******/
               ctx.beginPath()
               ctx.moveTo(50,50)
               ctx.lineTo(150,50)
               ctx.lineTo(150,150)
               ctx.lineTo(50,150)
               ctx.closePath()
               ctx.fill()
               ctx.stroke()

               //在(160,50)位置绘制一个宽高都为100的矩形
               ctx.fillRect(160,50,100,100)
               //采用清空的模式在(185,75)绘制出一个矩形
               ctx.clearRect(185,75,50,50)
               //在(270,50)绘制出一个长宽为50的矩形边框
               ctx.strokeRect(270,50,50,50)

               /******绘制圆弧******/
               //以(330,75)为中心,半径为50,起始角为0,终止角为120,绘制逆时针圆弧
               ctx.beginPath()
               ctx.arc(380,75, 50, 0, -1*Math.PI*120/180,true)
               ctx.stroke()

               /******绘制圆角矩形*****/
               ctx.beginPath()
               ctx.roundedRect(440, 75, 100, 60, 5, 5)
               ctx.fill()

               /******绘制贝塞尔曲线******/
               //以(50,200)为起始点,(80,190)和(110,280)为控制点,(150,220)为终点
               ctx.beginPath()
               ctx.moveTo(50, 200)
               ctx.bezierCurveTo(80, 190, 110, 280, 150, 220)
               ctx.stroke()

               /******绘制文本******/
               ctx.lineWidth = 1
               ctx.font="70px Arial";
               ctx.fillText("QML测试",160,220)

               /******绘制渐变色******/
               var gradient = ctx.createLinearGradient(50,250,150,250)
               //定义线性变化中某个位置的颜色
               gradient.addColorStop(0,"blue")
               gradient.addColorStop(0.5, "lightsteelblue")
               ctx.fillStyle = gradient
               //在线性变化的区域内绘制矩形
               ctx.fillRect(50,250,150,50);

               /******绘制带阴影效果的文字******/
               //阴影的属性
               ctx.shadowColor = "blue"
               ctx.shadowOffsetX = 5;
               ctx.shadowOffsetY = 5;
               //字体的样式
               ctx.font="70px Arial";
               ctx.fillStyle = "#33a9ff";
               ctx.fillText("阴影文字效果",60,380);

               /******绘制图片******/
               //在x=350,y=310的位置绘制对应的图片
               ctx.shadowOffsetX = 0;
               ctx.shadowOffsetY = 0;
               ctx.drawImage("qrc:/images/test.jpg", 500, 310)

           }
           //在绘制图片之前先缓存对应的图片
           Component.onCompleted: {
               loadImage("qrc:/images/test.jpg")
           }
       }
}

绘制效果如下图所示:

移动旋转坐标系

画布有多种方式来转换坐标系。这些操作非常类似于QML元素的转换。你可以通过缩放(scale),旋转(rotate),translate(移动)来转换坐标系。与QML元素不同的是,Canvas转换原点通常是画布的原点。

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Canvas Element")
    Canvas {
        id: root
        width: 400; height: 400
        onPaint: {
                var ctx = getContext("2d");
                ctx.lineWidth = 4;
                ctx.strokeStyle = "blue";
                //移动画布的坐标系
                
                ctx.translate(root.width/2, root.height/2);
                // 绘制矩形
                ctx.beginPath();
                ctx.rect(-40, -40, 80, 80);
                ctx.stroke();

                // 旋转坐标系
                ctx.rotate(Math.PI/3);
                ctx.strokeStyle = "green";

                // 旋转坐标系之后绘制矩形
                ctx.beginPath();
                ctx.rect(-40, -40, 80, 80);
                ctx.stroke();
        }
    }
}

?显示效果如下图所示:

多个绘制元素的组合模式

组合允许你绘制一个形状与已经有的像素点集合混合。画布提供了多种组合模式,使用globalCompositeOperation(mode)来设置。

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Canvas Element")
    Canvas {
        id: root
        width: 600; height: 400

        //各种组合模式
        property var operation : [
            'source-over', 'source-in', 'source-over',
            'source-atop', 'destination-over', 'destination-in',
            'destination-out', 'destination-atop', 'lighter',
            'copy', 'xor', 'qt-clear', 'qt-destination',
            'qt-multiply', 'qt-screen', 'qt-overlay', 'qt-darken',
            'qt-lighten', 'qt-color-dodge', 'qt-color-burn',
            'qt-hard-light', 'qt-soft-light', 'qt-difference',
            'qt-exclusion'
            ]

        onPaint: {
            var ctx = getContext('2d')

            for(var i=0; i<operation.length; i++) {
                var dx = Math.floor(i%6)*100
                var dy = Math.floor(i/6)*100
                ctx.save()
                //绘制对应的矩形
                ctx.fillStyle = '#4D9CF8'
                ctx.fillRect(10+dx,10+dy,60,60)
                //设置组合模式和透明度
                ctx.globalCompositeOperation = root.operation[i]
                ctx.fillStyle = '#FF33A7'
                ctx.globalAlpha = 0.75
                //绘制对应的圆弧
                ctx.beginPath()
                ctx.arc(60+dx, 60+dy, 30, 0, 2*Math.PI)
                ctx.closePath()
                ctx.fill()
                ctx.restore()
            }
        }
    }
}

Canvas对象实现像素缓冲

当你使用画布的时候,你可以检索读取画布上的像素数据,或者操作画布上的像素。读取像素数据使用createImageData(sw,sh)或者getImageData(sx,sy,sw,sh)。这两个函数都会返回一个含宽度(width)高度(height)和数据(data)的图像数据对象(ImageDta)。图像数据包含了一维数组像素数据,使用RGBA格式进行检索。每个像素的数据范围在0-255之间。设置画布像素数据可以使用putImageData(imagedata,dx,dy)函数来完成。也可以将画布数据保存到图片中。通过save(path)或者toDataURL(mimeType)来完成导出。

像素缓冲其实就是将画布上的内容保存成一个二进制块,可以将对二进制块中的数据进行处理也可以将二进制块保存成对应的图片。

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Canvas Element")
    Canvas {
        id: root
        width: 600; height: 400
        onPaint: {
            var ctx = getContext("2d");
            draw(ctx);
        }
        //点击鼠标左键之后将渲染的结果保存到某个元素中
        MouseArea{
            anchors.fill: parent
            onClicked: {
                var url = root.toDataURL('image/png')
                //将渲染的图片结构作为另一个元素的输入
                print('image url =',url)
                image.source = url
            }
        }
        Image{
            id: image
            x: 200; y:100
            width:300
            height:300
        }
        Timer{
            interval: 1000
            running: true
            triggeredOnStart: true
            repeat: true
            onTriggered: root.requestPaint()
        }

        function draw(ctx) {
            //绘制一个渐变矩形
            var gradient = ctx.createLinearGradient(50,250,150,250)
            gradient.addColorStop(0,"blue")
            gradient.addColorStop(0.5, "lightsteelblue")
            ctx.fillStyle = gradient
            ctx.fillRect(50,50,150,50);
        }
    }
}

绘制效果如下图所示:

?

通过Canvas实现一个简单的画板软件

依据简单的绘图需求,制作一个可以改变画笔颜色的画图程序,程序代码如下:

import QtQuick 2.8
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Canvas Element")

    //最外面的大边框
    Rectangle {
        width: 400; height: 300
        color: "#333333"
        //颜色选择栏
        Row {
            id: colorTools
            anchors {
                horizontalCenter: parent.horizontalCenter
                top: parent.top
                topMargin: 8
            }
            property variant activeSquare: red
            property color paintColor: "#33B5E5"
            spacing: 4
            Repeater {
                model: ["#33B5E5", "#99CC00", "#FFBB33", "#FF4444"]
                Rectangle {
                    id: red
                    color: modelData
                    width: 20
                    height: 20
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            colorTools.paintColor = color
                        }
                    }


                }
            }
        }

        //画图区的外边框
        Rectangle {
            anchors.fill: canvas
            border.color: "#666666"
            border.width: 4
        }

        //真正的绘图区
        Canvas {
            id: canvas
            anchors {
                left: parent.left
                right: parent.right
                top: colorTools.bottom
                bottom: parent.bottom
                margins: 8
            }
            property real lastX
            property real lastY
            property color color: colorTools.paintColor

            //每次绘制都得重新计算绘制点
            onPaint: {
                var ctx = getContext('2d')
                ctx.lineWidth = 1.5
                ctx.strokeStyle = canvas.color
                ctx.beginPath()
                ctx.moveTo(lastX, lastY)
                lastX = area.mouseX
                lastY = area.mouseY
                ctx.lineTo(lastX, lastY)
                ctx.stroke()
            }
            //每次位置变换都得重绘
            MouseArea {
                id: area
                anchors.fill: parent
                onPressed: {
                    canvas.lastX = mouseX
                    canvas.lastY = mouseY
                }
                onPositionChanged: {
                    canvas.requestPaint()
                }
            }
        }
    }
}

程序的运行效果如下图所示:

?

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 18:27:19  更:2022-04-22 18:27:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:50:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码