年底了,闲了几天,就学习了一下QML,完成一个鼠标可以交互操作的矩形绘制,个人可以想到的用途就是图像里面的ROI的设置和选取,还是有意义的,各位看完可以继续开发旋转功能,以便适应更多的应用场景。
先上个整体效果图:
1.先建立个Qt Quick 程序,我的主要QML文档如下:main.qml和Myrect.qml.前者是给窗体,用来布局Myrect元素;后者包含了矩形绘制和鼠标响应的逻辑。由于用到鼠标位置的计算,我还插入了C++类来帮助计算。
1.1 main.qml 的主要内容如下:创建 Myrect实例,然后在左下角用两个text来记录矩形左上角的坐标,要不光移动太单调,很无聊。
import QtQuick 2.12 import QtQuick.Window 2.12 Window { visible: true 640 height: 480 title: qsTr("Hello World") Rectangle { 500 height: 500 anchors.fill: parent Myrect { id:testrect clr:"red" } Text { anchors.bottom: parent.bottom anchors.left: parent.left id: xpos text: qsTr("Xpos:"+testrect.rect_X.toString()) font.pointSize: 25 } Text { anchors.bottom: parent.bottom anchors.left: xpos.right id: ypos text: qsTr("Ypos:"+testrect.rect_X.toString()) font.pointSize: 25 } } }
1.2 Myrect.qml的主要内容如下:主要完成矩形绘制和鼠标交互的逻辑处理。
注意两点:
A: acceptedButtons: Qt.LeftButton|Qt.RightButton 必须写上,要不默认是右键不响应的;
B:onPositionChanged:相当于Vs里面的鼠标移动响应。
1 import QtQuick 2.0 2 3 Item 4 { 5 id:myrect 6 anchors.fill: parent 7 8 property int rect_X: 0 9 property int rect_Y: 0 10 property int rect_X1: 100 11 property int rect_Y1: 100 12 // property int rect_W: rect_X1-rect_X 13 // property int rect_H: rect_Y1-rect_Y 14 property int rectline 5 15 property var clr: null 16 onRect_XChanged:myrect_root.requestPaint(); 17 onRect_YChanged:myrect_root.requestPaint(); 18 onRect_X1Changed:myrect_root.requestPaint(); 19 onRect_Y1Changed:myrect_root.requestPaint(); 20 21 22 Canvas 23 { 24 25 parent.width 26 // console.log: (width) 27 height: parent.height 28 id:myrect_root 29 anchors.fill: parent 30 31 // var ctx= getContext("2d") 32 onPaint: 33 { 34 var ctx= getContext("2d") 35 ctx.clearRect(0,0,myrect_root.width,myrect_root.height); 36 ctx.beginPath() 37 ctx.lineWidth=rectlinewidth 38 if(clr==null) 39 { 40 ctx.strokeStyle="green" 41 } 42 else 43 { 44 ctx.strokeStyle=clr 45 } 46 ctx.rect(rect_X,rect_Y,(rect_X1-rect_X),(rect_Y1-rect_Y)) 47 ctx.stroke() 48 ctx 49 } 50 51 } 52 53 MouseArea 54 { 55 56 property int leftmodifyflag: -1 57 property int rightmodifytype: -1 58 property int rightmodifyflag: -1 59 anchors.fill: parent 60 id:mousezoon 61 enabled: true 62 hoverEnabled: true 63 acceptedButtons: Qt.LeftButton|Qt.RightButton 64 function calRightMousetype(mxpos,mypos,rectx,recty,rectw,recth ) 65 { 66 return mousemath.calRihgtMouseType(mxpos,mypos,rectx,recty,rectw,recth) 67 } 68 69 onClicked: 70 { 71 var rect_W=rect_X1-rect_X 72 var rect_H=rect_Y1-rect_Y 73 74 if(mouse.button==Qt.LeftButton) 75 { 76 leftmodifyflag++ 77 leftmodifyflag=leftmodifyflag%2 78 console.log("leftmodifyflag:"+leftmodifyflag.toString()) 79 if(leftmodifyflag==1) 80 { 81 82 //change center point 83 rect_X=mouse.x-rect_W*0.5 84 rect_Y=mouse.y-rect_H*0.5 85 rect_X1=mouse.x+rect_W*0.5 86 rect_Y1=mouse.y+rect_H*0.5 87 88 } 89 // mouse.accepted=true 90 } 91 else if(mouse.button==Qt.RightButton) 92 { 93 rightmodifyflag++ 94 rightmodifyflag=rightmodifyflag%2 95 rightmodifytype=calRightMousetype(mouse.x,mouse.y,rect_X,rect_Y,rect_W,rect_H) 96 97 } 98 myconfig.rect_Xpro=rect_X; 99 myconfig.rect_Ypro=rect_Y; 100 myconfig.rect_X1pro=rect_X; 101 myconfig.rect_Y1pro=rect_Y1; 102 103 //myconfig.writeConfig(); 104 } 105 106 onPositionChanged: 107 { 108 var rect_W=rect_X1-rect_X 109 var rect_H=rect_Y1-rect_Y 110 if(leftmodifyflag==0) 111 { 112 // rect_W=rect_X1-rect_X 113 // rect_H=rect_Y1-rect_Y 114 //change center point 115 rect_X=mouse.x-rect_W*0.5 116 rect_Y=mouse.y-rect_H*0.5 117 rect_X1=mouse.x+rect_W*0.5 118 rect_Y1=mouse.y+rect_H*0.5 119 } 120 else if(rightmodifyflag==0) 121 { 122 console.log(rightmodifytype.toString()) 123 switch(rightmodifytype) 124 { 125 case 0: 126 //left 127 rect_X=mouse.x 128 break 129 case 1: 130 //up 131 rect_Y=mouse.y 132 break 133 case 2: 134 //right 135 rect_X1=mouse.x 136 break 137 case 3: 138 //up 139 rect_Y1=mouse.y 140 break 141 default: 142 //left 143 rect_X=mouse.x 144 break 145 } 146 } 147 myconfig.rect_Xpro=rect_X; 148 myconfig.rect_Ypro=rect_Y; 149 myconfig.rect_X1pro=rect_X; 150 myconfig.rect_Y1pro=rect_Y1; 151 152 // myconfig.writeConfig(); 153 } 154 } 155 156 }
2:C++数据处理部分:主要完成鼠标点击位置和矩形4边位置关系的计算。主要需要知道Qml调用C++的方法。
1 #ifndef MOUSEMOVINGMATH_H 2 #define MOUSEMOVINGMATH_H 3 4 #endif // MOUSEMOVINGMATH_H 5 #include <QObject> 6 7 class MouseMovingMath:public QObject 8 { 9 Q_OBJECT 10 public: 11 MouseMovingMath(); 12 ~MouseMovingMath(); 13 public : 14 Q_INVOKABLE int calRihgtMouseType(const int mxpos,const int mypos,int rectx,int recty,int recw,int recth ); 15 16 Q_INVOKABLE int test( ); 17 18 } 19 ;
1 #include "MyrectConfig.h" 2 3 MyrectConfig::MyrectConfig(QString configfilename):Myconfig(configfilename) 4 { 5 6 node="RectProperty"; 7 } 8 9 MyrectConfig::~MyrectConfig() 10 { 11 12 } 13 14 void MyrectConfig::readConfig() 15 { 16 rect_X= getValue(node,"rect_X").toInt(); 17 rect_Y= getValue(node,"rect_Y").toInt(); 18 rect_X1= getValue(node,"rect_X1").toInt(); 19 rect_Y1= getValue(node,"rect_Y1").toInt(); 20 rect_Color=getValue(node,"rect_Color").toString(); 21 //Transfer color data 22 auto colorarray= rect_Color.split(";",QString::SplitBehavior::SkipEmptyParts,Qt::CaseSensitivity::CaseSensitive); 23 if(colorarray.length()==4) 24 { 25 rect_color_r=colorarray[0].toFloat(); 26 rect_color_g=colorarray[1].toFloat(); 27 rect_color_b=colorarray[2].toFloat(); 28 rect_color_a=colorarray[3].toFloat(); 29 30 } 31 else 32 { 33 rect_color_r=0.1; 34 rect_color_g=0.1; 35 rect_color_b=0.1; 36 rect_color_a=1; 37 } 38 } 39 void MyrectConfig::writeConfig() 40 { 41 setValue(node,"rect_X",rect_X); 42 setValue(node,"rect_Y",rect_Y); 43 setValue(node,"rect_X1",rect_X1); 44 setValue(node,"rect_Y1",rect_Y1); 45 rect_Color=QString("%1;%2;%3;%4").arg(rect_color_r).arg(rect_color_g).arg(rect_color_b).arg(rect_color_a); 46 setValue(node,"rect_Color",rect_Color); 47 } 48 49 int MyrectConfig::rect_Xpro() 50 { 51 return rect_X; 52 } 53 int MyrectConfig::rect_Ypro() 54 { 55 return rect_Y; 56 } 57 int MyrectConfig::rect_X1pro() 58 { 59 return rect_X1; 60 } 61 int MyrectConfig::rect_Y1pro() 62 { 63 return rect_Y1; 64 } 65 66 void MyrectConfig::set_rect_Xpro(int v) 67 { 68 rect_X=v; 69 } 70 void MyrectConfig::set_rect_Ypro(int v) 71 { 72 rect_Y=v; 73 } 74 void MyrectConfig::set_rect_X1pro(int v) 75 { 76 rect_X1=v; 77 } 78 void MyrectConfig::set_rect_Y1pro(int v) 79 { 80 rect_Y1=v; 81 } 82 83 84 float MyrectConfig::rect_color_rpro() 85 { 86 return rect_color_r; 87 } 88 float MyrectConfig::rect_color_gpro() 89 { 90 return rect_color_g; 91 } 92 float MyrectConfig::rect_color_bpro() 93 { 94 return rect_color_b; 95 } 96 float MyrectConfig::rect_color_apro() 97 { 98 return rect_color_a; 99 } 100 101 void MyrectConfig::set_rect_color_rpro(float v) 102 { 103 rect_color_r=v; 104 } 105 void MyrectConfig::set_rect_color_gpro(float v) 106 { 107 rect_color_g=v; 108 } 109 void MyrectConfig::set_rect_color_bpro(float v) 110 { 111 rect_color_b=v; 112 } 113 void MyrectConfig::set_rect_color_apro(float v) 114 { 115 rect_color_a=v; 116 }
2.1:初始化C++函数的调用
engine.rootContext()->setContextProperty("mousemath",&mousemovingmath);
3.主要实现功能,左键点击一次,矩形将跟随着鼠标的中心移动,左键第二次,移动停止,再则周而复始。
右键点击一次,矩形最靠近右键点击位置的边将随着鼠标的移动,即改变矩形的大小,右键第二次,移动停止,再则周而复始。
上几个图,放置视频不可见。呵呵。
需要源码联系我!转载请注明出处。
BR!