前言:
在上一节中,我们了解了Rectangle的基本使用,学习了如何通过帮助文档来了解qml代码。这一节,我们继续对Rectangle做更深入的了解,并结合MouseArea的使用,为其添加鼠标相应的功能。
一、给Rectangle添加一个MouseArea
我们先打开帮助文档,查看一下MouseArea是怎么说的?
A MouseArea is an invisible item that is typically used in conjunction with a visible item in order to provide mouse handling for that item. By effectively acting as a proxy, the logic for mouse handling can be contained within a MouseArea item.
MouseArea是一个不可见的组件,通常与可见组件配合使用,以便为该组件提供鼠标处理功能。通过有效地充当代理,可以将鼠标处理的逻辑包含在MouseArea组件中。
也就是说,通过在Rectangle中添加一个不可见的MouseArea组件,就能给Rectangle提供鼠标处理的功能了。
我们先在上一节的QmlSyntax工程中,为Rectangle添加MouseArea,这里附上完整代码:
cpp
import QtQuick 2.14
import QtQuick.Window 2.14
Window {
visible: true
width: 640
height: 480
title: qsTr("QML Syntax Demo")
Rectangle{
id: redRectId
width: 100
height: 100
color: "red"
// 设置位置
x: 20
y: 20
// anchors.centerIn: parent
// 边框设置
radius: 20
border.color: "black"
border.width: 5
//鼠标响应
MouseArea{
anchors.fill: parent // 告诉Area填充满整个矩形
onClicked: { // 类似于信号槽
console.log("Mouse Click on the red rectangle")
}
}
}
}
可以看到,鼠标点击时成功打印出信息。
这里有两个知识点:
1.anchors.fill: parent ,毕竟Area是区域的意思,这是为了告诉Area要填充满整个矩形,这样才能监听整个矩形的鼠标活动。另外,这里的parent其实可以用redRectId来进行替换,毕竟这个才是Rectangle的名字嘛。
2.onClick:{},这是qml中槽函数的写法,在这里不再赘述。事实上在之后详细讲述的一系列控件中,也经常会出现这个onClick。
总结一下:
我们可以理解为Rectangle作为一个基本的容器组件,类似于QFrame或QWidget,本身设计出来并不是为了响应鼠标事件的,所以天生不自带类似于Button或QPushbutton的点击槽函数。但这里,我们可以人为地给Rectangle添加一个鼠标区域组件,以此来给它赋上鼠标相关的功能。
二、利用MouseArea实现鼠标三态,让Rectangle模拟Button组件
上一小节中,我们通过MouseArea成功捕获到鼠标点击事件,对应是QWidget中的clicked信号和槽函数。但对于UI效果而言,这种程度的使用还远远不够。一个最常见的UI效果:我们需要对一个按钮设置样式,实现常态、鼠标悬停、鼠标点击三种状态的不同效果。我将这个称之为"鼠标三态"。
想要实现"鼠标三态",我们需要先捕获到这三种状态,得到相应的"槽函数"入口,才能做进一步的设计。(是的)
这里我们有几个你可能需要用到的槽函数:
onEntered:鼠标进入,指的是鼠标进入到MouseArea区域时会触发;
onExited:鼠标离开,指的是鼠标从MouseArea区域中移出时会触发;
onPressed:鼠标点击,指的是鼠标按下的那一刻,所触发的动作;
onReleased:鼠标释放,指的是鼠标从按下的状态释放时,所触发的动作。
我们直接为四种状态添加不同的颜色,看下效果:
cpp
//鼠标响应
MouseArea{
anchors.fill: parent // 告诉Area填充满整个矩形
onClicked: { // 类似于信号槽
console.log("Mouse Click on the red rectangle")
}
hoverEnabled: true
onEntered: parent.color = "black" // 悬停
onExited: parent.color = "green" // 返回常态
onPressed: parent.color = "blue" // 点击
onReleased: parent.color = "grey" // 返回悬停(或常态)
}
以下是gif的效果:(因为录不到鼠标,所以看上去差点意思)
别忘了,这个Rectangle原本是红色的的,当我们把鼠标移上去的时候,变成黑色了,点击后变成了蓝色,松开鼠标变成灰色,移出Rectangle变成了绿色,完全符合我的预期。
需要注意的是,想要监听悬停事件,也就是hover,必须要先打开hoverEnabled标志。
另外,我们发现这几种状态的切花,只是修改了背景颜色,但边框样式还是不变的,如果需要改变的话,可以直接增加{},在里面写复杂的代码。
除了这种样式上的变化,onReleased也可以当做onClicked,都是鼠标点击的意思,是不是很有趣?所以我们完全可以在里面写更加复杂的代码,但现阶段还没有必要。
三、总结:
当然,这种鼠标三态的样式还只是入门级别的。如果需要对一个组件进行更复杂的样式定制,比方说它有"模式A"和"模式B"两种方式,这样会怎样?
不懂我在说什么?假设有一个用于打开和关闭的复合型按钮,它会在打开和关闭两种模式下不断切换,假设提示打开的时候它是绿色的,提示关闭的时候是红色的,这种需求可是超级常见的哦。
在QWidget中,因为是通过样式表的方式来写,所以要不在代码中设置两套不同的样式表,要不直接在样式表中添加状态标志,区分两种状态。
而在qml中也会有相应的实现方法,这一点不用担心。但更复杂的,我们以后再来实现吧。