900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > QML 实现九宫格图案解锁

QML 实现九宫格图案解锁

时间:2021-10-02 22:12:03

相关推荐

QML 实现九宫格图案解锁

《QML基础教程》总目录

图案解锁

一、演示二、简述三、代码

一、演示

支持自定义行列数;

支持自定义颜色;

支持自定义吸附半径。

二、简述

1.使用GridView显示圆圈,方便自定义。数据模型使用一个selectedIndex数组,保存选中index。

2.画线使用Canvas,借助选中的索引数组,变化时刷新连线。

3.鼠标检测使用一个MouseArea,当光标移动时,检测光标位置所处的格子索引,再做坐标转换。计算光标距离格子中心的半径,处于圆圈中就选中该索引。

三、代码

main.qml

import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")PatternPassword{width: 300height: 300anchors.centerIn: parentonReleased: console.log("released:",selectIndexs)}}

图案解锁控件源码

import QtQuick/*图案密码控件通过width,height指定控件的宽高。row,column指定图案密码的行数和列数。网格宽=width/column,网格高=height/row。通过hotRadius指定网格中圆圈的半径,单位像素。半径以内可以吸附线。、lineWidth指定线宽,单位像素。[signal] released() 图案松开信号,通过selectIndexs获取选中的点。index从0开始,从左到右依次+1。*/Item {id: rootproperty int row: 4//网格行数property int column: 4 //网格列数property int pressedIndex: -1//鼠标按到了某个网格的热区内property var selectIndexs: []//鼠标滑过选中的点property int lineWidth: 6 //连线宽度,圆圈线宽property int hotRadius: Math.min(cellWidth,cellHeight) * 0.2 //热区半径,半径之内点会被选中property color color: "white"//圆圈颜色property color borderColor: "darkGray"//默认圆圈边框颜色property color selectedBorderColor: "gray" //选中圆圈边框颜色property color lineColor: "gray" //连线颜色readonly property alias pressed: mouseArea.pressed //网格中有鼠标按下readonly property alias cellWidth: gridView.cellWidth //网格宽度readonly property alias cellHeight: gridView.cellHeight //网格高度signal released() //图案松开//绘制选中点之间的连线Canvas{id: canvasanchors.fill: parentonPaint: {var ctx = getContext("2d")ctx.lineJoin = 'round';ctx.clearRect(0,0,canvas.width,canvas.height)if(0 === selectIndexs.length)return ;ctx.strokeStyle = root.lineColorctx.lineWidth = lineWidthfor(var i = 0; i < root.selectIndexs.length; i++) {var posX = (Math.floor(selectIndexs[i] % column) + 0.5) * cellWidthvar posY = (Math.floor(selectIndexs[i] / column) + 0.5) * cellHeightif(0 === i){ctx.beginPath()ctx.moveTo(posX, posY)}else{ctx.lineTo(posX, posY)}}ctx.lineTo(mouseArea.mouseX, mouseArea.mouseY)ctx.stroke()}}//图案网格圈显示GridView{id: gridViewanchors.fill: parentcellHeight: gridView.height / rowcellWidth: gridView.width / columninteractive: falsemodel: row * columndelegate: Item{property bool checked: root.pressed ? (pressedIndex === index? true : checked) : falsewidth: gridView.cellWidthheight: gridView.cellHeightRectangle{anchors.centerIn: parentwidth: hotRadius * 2height: widthborder.width: lineWidthborder.color: checked ? root.selectedBorderColor : root.borderColorcolor: root.colorradius: width / 2}}}//检测选中点模型管理MouseArea{id: mouseAreaanchors.fill: parentonPressedChanged: refresh()onMouseXChanged: refresh()onMouseYChanged: refresh()function refresh(){if (!pressed || mouseX >= width || mouseY >= height|| mouseX < 0 || mouseY < 0){canvas.requestPaint()return}//找到光标所在的格子var mouseRow = Math.floor(mouseY / cellHeight)var mouseColumn = Math.floor(mouseX / cellWidth)//坐标转换 以当前格子中心点为0,0点var newPosX = mouseX - (mouseColumn + 0.5) * cellWidthvar newPosY = mouseY - (mouseRow + 0.5) * cellHeight//计算与原点的距离,判断是否在圆形热区中var distance = Math.sqrt(newPosX * newPosX + newPosY * newPosY);if (distance < hotRadius) {//计算热区的index,添加选中var index = mouseRow * root.column + mouseColumnif(-1 === selectIndexs.indexOf(index)) {selectIndexs.push(index)pressedIndex = index}}else{pressedIndex = -1}//重绘连线canvas.requestPaint()}onPressed: selectIndexs = []onReleased: {root.released()selectIndexs = []}}}

由于作者能力有限,文章难免疏漏,如有错误之处,欢迎指出,及时更改

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。