QML 中 QtQuick.Controls 模块提供的
Button
组件能购满足我们绝大多数的使用场景,但是很多情况下,尤其是在复杂页面的制作过程中,我们的按钮要保证和界面具有高度的统一性,就需要自己定义按钮的外观及响应动画,这个时候我们就需要自己封装一个按钮组件。
最终效果如下:
一、准备工作
- OS:Windows 10 X64
- Qt:Qt 6.5.X
- IDE:Qt Creator 10.0.1
- 前置知识:Rectangle、Text、Image、MouseArea等组件的使用;QML信号响应
二、要实现的功能
- 按钮可以设置文本/图片
- 鼠标悬浮高亮
- 点击有动画反馈
- 组件可以挂载 onClicked 事件
三、实现构思
如上图所示,我们可以绘制一个矩形(Rectangle),然后在矩形内填充一个Image
组件和Text
组件,用来盛放按钮的图片或文本,最后在Rectangle
范围内填充一个MouseArea
,来响应鼠标悬浮高亮、点击事件
四、代码实现
新建一个 CustomButton.qml
文件:
- 先绘制按钮
Rectangle {
id: customBtn
width: 50
height:50
Text {
id: customBtnText
anchors.centerIn: parent
text: ""
elide: Text.ElideRight
}
Image {
id: customBtnIcon
anchors.centerIn: parent
width:parent.width
height: parent.height
source: ""
}
}
- 再设置鼠标响应事件
Rectangle {
signal clicked
id: customBtn
// ...
MouseArea {
anchors.fill: parent
preventStealing:true
hoverEnabled: true
onEntered: parent.color = "lightgray"
onExited: parent.color = "transparent"
enabled: true
onReleased: {
customBtn.clicked()
}
}
// ...
}
- 添加动画反馈
Rectangle {
id: customBtn
// ...
property real pressScale: 0.95
Behavior on scale {
NumberAnimation {
duration: 100
easing.type: Easing.InOutQuad
}
}
MouseArea {
anchors.fill: parent
preventStealing:true
hoverEnabled: true
onEntered: parent.color = "lightgray"
onExited: parent.color = "transparent"
enabled: true
onPressed: customBtn.scale = customBtn.pressScale
onReleased: {
customBtn.scale = 1;
// ...
}
}
// ...
}
- 封装组件,添加必要的属性
Rectangle {
id: customBtn
width: 1
height:1
property alias source: customBtnIcon.source
property alias text: customBtnText.text
// ...
// 如果没有传入 width、height属性,根据text内容自动调整大小
Component.onCompleted: {
customBtn.width = customBtn.width === 1 ? customBtnText.width + 10 : customBtn.width
customBtn.height = customBtn.height === 1 ? customBtnText.width + 10 : customBtn.height
}
}
至此,一个相对完整的 Button 组件就封装完成了,我们可以从外部调用,在同级目录下新建一个 main.qml
文件,添加以下内容:
import QtQuick
Rectangle {
width: 100
height: 100
CustomButton {
anchors.centerIn: parent
// text: "收集"
source: "shot.png"
width: 50
height: 50
onClicked:{
console.log('hhhhhhh')
}
}
}