这两个 demo 覆盖鼠标交互最基础的能力:怎么接收点击,怎么感知鼠标是否悬停在区域上,怎么拿到点击的具体位置。学会了它们,就理解了 MouseArea 的核心用法,后面的拖拽、缩放、自定义按钮都是在这个基础之上实现的。
这篇介绍两个 demo:
- 基础点击与悬停 --- 点击计数,鼠标移入移出时,边框加粗提示
- 点击坐标获取 --- 在点击处画标记点,实时显示最近一次点击的坐标
点击与悬停

效果很简单:一个圆角方块,每点击一次标题下方的数字加1,方块本身的颜色在两种淡蓝之间切换;鼠标悬停在方块上时边框加粗,下方一行文字实时显示鼠标在区域内还是区域外。
演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
TitleSeparator {
title: "基础点击与悬停"
description: "演示 MouseArea 的 clicked 信号与 containsMouse 悬停状态检测"
}
Rectangle {
id: box
Layout.fillWidth: true
Layout.fillHeight: true
radius: 8
color: clickCount % 2 === 0 ? "#EAF4FF" : "#BCE6FF"
border.width: mouseArea.containsMouse ? 3 : 1
border.color: "#1296FF"
property int clickCount: 0
Text {
anchors.centerIn: parent
text: "点击我\n已点击: " + box.clickCount + " 次"
font.pointSize: 14
color: "#1296FF"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: box.clickCount++
}
}
Text {
Layout.alignment: Qt.AlignHCenter
text: "悬停状态: " + (mouseArea.containsMouse ? "鼠标在内" : "鼠标在外")
font.pointSize: 12
color: "#999"
}
}
}
关键逻辑解析
MouseArea 是什么
MouseArea 是 QML 里接收鼠标操作的透明区域控件。它本身不可见,通常铺在某个可见控件(这里是 Rectangle)上面,通过 anchors.fill: parent 让它铺满整个方块。鼠标落在方块上,就等于落在 MouseArea 上,点击、悬停都能感知到。
点击计数
onClicked: box.clickCount++ 是 MouseArea 的点击信号处理器,鼠标左键点一下触发一次。这里每次点击给自定义属性 clickCount 加一,这个 property int clickCount 是给方块额外定义的一个整数属性,可以在 QML 里随意声明。
方块颜色用取余切换:clickCount % 2 === 0 判断是偶数还是奇数,偶数用浅色,奇数用深色,这样每点一次颜色就换一次,视觉上有反馈。
悬停检测
判断鼠标在不在区域里无需监听坐标,其实 MouseArea 内置了 containsMouse 这个只读属性,直接用即可。它返回 true 表示鼠标在区域内,false 表示在外面。
但有个前提:必须开 hoverEnabled: true。默认它是关的,关着的时候 MouseArea 只在按下、点击这类操作时才有反应,鼠标单纯划过不感知。开了之后才能跟踪悬停,containsMouse 才有意义,边框加粗和下方"鼠标在内/在外"的文字才会跟着变。
点击坐标获取

MouseArea 的点击信号会带一个 mouse 参数,里面存了本次点击的坐标。这个 demo 用 mouse.x、mouse.y 在点击处画一个小圆点,并且实时更新一行文字显示最近一次点击的坐标。
演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
TitleSeparator {
title: "点击坐标获取"
description: "通过 mouse.x / mouse.y 获取点击位置,并在点击处绘制标记点"
}
Rectangle {
id: canvas
Layout.fillWidth: true
Layout.fillHeight: true
radius: 8
color: "#FAFAFA"
border.color: "#ddd"
border.width: 1
clip: true
// 点击标记点
Repeater {
model: clickModel
delegate: Rectangle {
x: model.x - 8
y: model.y - 8
width: 16
height: 16
radius: 8
color: "#1296FF"
opacity: 0.7
Text {
anchors.centerIn: parent
text: index + 1
color: "white"
font.pixelSize: 9
font.bold: true
}
SequentialAnimation on opacity {
loops: Animation.Infinite
NumberAnimation { from: 0.7; to: 0.3; duration: 1000 }
NumberAnimation { from: 0.3; to: 0.7; duration: 1000 }
}
}
}
// 最新点击位置连线指示
Text {
id: hintText
anchors.centerIn: parent
text: "在区域内点击以标记位置"
color: "#999"
font.pointSize: 13
visible: clickModel.count === 0
}
ListModel { id: clickModel }
MouseArea {
id: clickArea
anchors.fill: parent
onClicked: (mouse) => {
clickModel.append({ x: mouse.x, y: mouse.y })
if (clickModel.count > 10)
clickModel.remove(0)
coordText.text = "最近点击: (" + Math.round(mouse.x) + ", " + Math.round(mouse.y) + ")"
}
}
}
RowLayout {
Layout.alignment: Qt.AlignHCenter
spacing: 20
Text {
id: coordText
text: "最近点击: (-, -)"
font.pointSize: 12
color: "#999"
}
Button {
text: "清除标记"
onClicked: {
clickModel.clear()
coordText.text = "最近点击: (-, -)"
}
}
}
}
}
关键逻辑解析
拿到点击坐标
onClicked: (mouse) => { ... } 这里的 mouse 是信号自带的事件对象,mouse.x、mouse.y 就是本次点击在 MouseArea 区域内的横向和纵向位置(原点在方块左上角)。这是再普通不过的操作------用鼠标交互,十有八九都要读坐标,比如画板、游戏、地图都靠它定位。
点击处画圆点
项目用 Repeater 配 ListModel 来做:每点一次,onClicked 里往 clickModel 加一条数据,记录 x、y;Repeater 自动为每条数据创建一个圆点,x、y 减去半径 8,让圆点中心正好落在点击处。点多了就把最老的删掉(超过 10 个时 remove(0)),保持界面清爽。
这套"数据里有内容、界面按内容画",也就是 QML 的模型-视图分工。clickModel 只管存点击的位置,界面上有几个点由它决定,自己不用手动增删控件。
圆点动画
圆点加了透明度呼吸的循环动画(opacity 在 0.7 和 0.3 之间来回),让标记点有轻微闪烁感,视觉上更醒目。这只是锦上添花,演示 Repeater 的每个子项都能独立配动画,不影响坐标获取的核心逻辑。
运行验证
- Qt Creator 打开示例的
CMakeLists.txt; - 按
Ctrl+R运行; - 基础点击与悬停:多点几次方块看计数和颜色切换,鼠标移出移入看边框粗细变化,看底部"鼠标在内/在外"文字;
- 点击坐标获取:在区域里点几下看出现带顺序号的圆点,看底部实时更新的坐标,点"清除标记"看圆点全部消失。
扩展复用方向
- 点击计数可以扩展成"统计不同按键的点击次数",为后面的多按键 demo 做铺垫
- 坐标获取配合
Drag可以做简单的画板:按下拖动画线 - 把"点击位置加圆点"这套抽成组件,做成可复用的标记层
containsMouse常用来做工具条、按钮的悬浮高亮,很多悬停交互都可以用它
已验证环境:
- Qt 版本:Qt 6.8、Qt 6.11
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_mousearea