QML MouseArea学习小结

QML中的MouseArea类型为用户进行简单的鼠标操作提供了方便。

MouseArea是一个不可见的Item,通常与可见项目结合使用,以便为该项目提供鼠标处理。通过有效地充当代理,鼠标处理的逻辑可以包含在MouseArea Item中。

MouseArea虽然是一个不可见的Item,但是它有一个“visible”属性,当该属性为假时,鼠标区域就对鼠标事件变得透明。

MouseArea使用实例:

main.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
import  QtQuick  2 . 12
import  QtQuick.Window  2 . 12

Window
{
    id : window
    visible : 
true
    width : 
640
    height : 
480
    title : qsTr(
"Mouse Area" )

    Rectangle
    {
        id : rect
        anchors.left : window.left
        anchors.leftMargin : 
10
        width : 
100 ;
        height : 
100
        color : 
"green"

        MouseArea
        {
            anchors.fill : parent
            onClicked :
            {
                parent.color = 
'red' ;
            }
        }
    }

    Rectangle
    {
        id : roundrect
        anchors.left : rect.right
        anchors.leftMargin : 
10
        width : 
100 ;
        height : 
100
        color : 
"red"
        radius : 
20

        MouseArea
        {
            anchors.fill : parent
            onClicked :
            {
                parent.color = 
'green'
            }
        }
    }
}

常规测试实验证实,MouseArea有一个矩形的形状区域,这就会导致一些不是矩形形状的Item不能有效地获取实际形状的鼠标操作区域。如圆角矩形,在圆形按钮周围的假想方块的角落的鼠标操作也会被捕获,这显然不符合精准拾取的现实。

进阶地,文章“How to create a round mouse area in QML “提供了一种圆形鼠标区域RoundMouseArea:

RoundMouseArea.qml 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
import  QtQuick  2 . 0

Item {
    id: roundMouseArea

    property alias mouseX: mouseArea.mouseX
    property alias mouseY: mouseArea.mouseY

    property bool containsMouse: {
        
var  x1 = width /  2 ;
        
var  y1 = height /  2 ;
        
var  x2 = mouseX;
        
var  y2 = mouseY;
        
var  distanceFromCenter = Math.pow(x1 - x2,  2 ) + Math.pow(y1 - y2,  2 );
        
var  radiusSquared = Math.pow(Math.min(width, height) /  2 2 );
        
var  isWithinOurRadius = distanceFromCenter < radiusSquared;
        
return  isWithinOurRadius;
    }

    readonly property bool pressed: containsMouse && mouseArea.pressed

    signal clicked

    MouseArea {
        id: mouseArea
        anchors.fill: parent
        hoverEnabled: 
true
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        onClicked: 
if  (roundMouseArea.containsMouse) roundMouseArea.clicked()
    }
}

main.qml中使用:

main.qml片段 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
RoundMouseArea {
    id : roundMouseArea
    width :  100
    height : 
100
    anchors.centerIn : parent

    onClicked : print(
"clicked" )

    
// Show the boundary of the area and whether or not it's hovered.
    Rectangle     {
        color : roundMouseArea.pressed ? 
"red"  : (roundMouseArea.containsMouse ?  "darkorange"  :  "transparent" )
        border.color : 
"darkorange"
        radius : width / 
2
        anchors.fill : parent
    }
}

我们可以根据需要重写containsMouse来规定自己的鼠标区域,但是需要计算不同区域的数学知识,需要一定的功底。

再进一步,应该把鼠标区域一般化,可以使用任意的路径形状来表示才好。Qt自带一个例子maskedmousearea,此示例提供了一种使用任何形状的Mask的方法,它可以根据您的需求进行定制。

先睹为快:

该demo是一个异形窗口,主要展示鼠标在和异形区域交互的使用,如上图所示,当鼠标移动到白云或者月亮上时,相应的物体会高亮,当鼠标按下时,物体会有一个放大的动画效果,鼠标离开时恢复原样。

class MaskedMouseArea : public QQuickItem

核心主要时判断鼠标点是否在图片有效区域内:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
bool  MaskedMouseArea::contains( const  QPointF &point)  const
{
    
if  (!QQuickItem::contains(point) || m_maskImage.isNull())
        
return   false ;

    QPoint p = point.toPoint();

    
if  (p.x() <  0  || p.x() >= m_maskImage.width() ||
            p.y() < 
0  || p.y() >= m_maskImage.height())
        
return   false ;

    qreal r = qBound<
int >( 0 , m_alphaThreshold *  255 255 );
    
//根据alpha值判断 异形区域
     return  qAlpha(m_maskImage.pixel(p)) > r;
}
 qml Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
Image {
    id : moon
    anchors.centerIn : parent
    scale : moonArea.pressed ?  1 . 1  :  1 . 0
    opacity : moonArea.containsMouse ? 
1 . 0  :  0 . 7
    source : Qt.resolvedUrl(
"images/moon.png" )

    MaskedMouseArea {
        id : moonArea
        anchors.fill : parent
        alphaThreshold : 
0 . 4
        maskSource : moon.source
    }

    Behavior on opacity {
        NumberAnimation {
            duration : 
200
        }
    }
    Behavior on scale {
        NumberAnimation
        {
            duration : 
100
        }
    }
}

gif走起来:

转载于:https://www.cnblogs.com/MakeView660/p/11238608.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值