我们在使用QWidget编程时,如果你嫌弃QPushButton不够强大,那么你就可以继承它并写出一个子类来实现一个功能更强的按钮,如果你还不满意,你甚至可以继承QWidget来实现一个功能更强的按钮。
那么这种自定义操作,在QML中也是有的,叫【自定义组件】,或者叫【自定义元素】
本文将通过创建一个自定义按钮来演示一下。
新建一个QML文件,并命名为MyButton.qml,文件内容为:
//自定义一个可check的按钮类: MyButton
import QtQuick 2.7
Rectangle {
id: root
property bool checked: false //自定义成员变量(自定义属性),是否被选中
property alias text: btnText.text //自定义属性引用
signal toggled(var checked) //声明带参信号
color: "lightgreen";//背景色
border.color: "green"; //边框色
border.width: 5
height: 50
width: 100;
Text {
id: btnText
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: qsTr("按钮")
}
MouseArea
{
anchors.fill: parent
onClicked: { //MouseArea被点击时的槽
checked = !checked;
root.toggled(checked) //发射root元素的信号
console.log("btn clicked, " + checked)
}
onEntered: { //鼠标按下时的槽
parent.color = "green";
}
onExited: { //鼠标弹起时的槽
parent.color = "lightgreen";
}
}
}
代码解释:
1、property bool checked: false
声明变量,类似于C++里的: bool checked = alse;
当然,在QML里这不叫变量声明,叫属性声明,其实是一个意思。
2、property alias text: btnText.text
属性别名(又叫:声明一个属性引用)。语法格式为:property alias [自定义变量名]: [某个属性或者子元素的某个属性]
这一句中,当读写根元素的text,等价于读写btnText元素的text属性。这一功能类似于C/C++中声明一个变量引用:QString &text = btnText.text;
3、signal clicked
定义或声明一个信号,与QT-C++中声明信号函数,功能完全一致。
4、onClicked: {
checked = !checked;
root.toggled(checked) //发射root元素的信号(携带参数)
console.log("btn clicked, " + checked)
}
其中onClicked,其实是一个无参槽函数。onClicked实际上是一个组合词:on和Clicked,这实际上是绑定信号槽的一种快捷写法,只要把信号名首字母大写,并在前面加上单词on,那么这个属性就会成为这个信号的槽函数,而无需显式的调用connnect进行绑定,这一技巧在QT/C++中也是如此。
同理 onEntered、onExited 槽函数,也是如此。
在另一个QML中就可以使用这个自定义按钮了, 我们接着上一篇博文的代码,继续添加一个按钮和javascript写的槽函数:
import QtQuick 2.7
Item {
id: root
width: 200;
Image{ //表盘
id: dial
width: parent.width
height: width
source: "qrc:/pic/pic/meter.jpg"
Image{ //分针
id: minPin
height: parent.height / 2 * 0.7
width: height * 0.1
anchors.bottom: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
//以图片底部作为旋转(以及缩放)的中心
transformOrigin: Item.Bottom
//旋转一定角度
rotation: 45
source: "qrc:/pic/pic/pin.png"
NumberAnimation on rotation {id: minutePinAni; from: 0; to: 360; duration: 20000; loops: Animation.Infinite }
}
MyButton { //放置一个按钮
id: myBtn
text: "启/停"
anchors.top: dial.bottom //按钮的顶部,对齐到表盘的底部
anchors.left: parent.left //按钮的左边,对齐到窗口的左边
}
Component.onCompleted: { //QML载入完成时的槽
console.log("load ok")
myBtn.toggled.connect(whenBtnToggled); //绑定信号槽: myBtn.toggled(bool) -> whenBtnToggled(bool)
}
function whenBtnToggled(checked){//自定义js函数作为槽
if(checked)
minutePinAni.pause() //分针动画暂停
else
minutePinAni.resume() //分针动画继续
}
}
}