✤ Jan 11, 2015 ✤
今天,出于需求,需要在列表中用qt实现一个类似qml实现QQ列表界面侧划效果。经过我不懈打酱油+听音乐+发呆+刷新闻后终于得以实现,记录下~
对于这个神奇的控件,就称为DragBar,我所定义它的行为为:
因为是有拖动组件然后出现按钮这样的行为,所以我在实现时,利用MouseArea的drag属性,将两层组件覆盖在一起,于是如果你拖动上层组件,就自然而然会出现下层组件的外形。
drag provides a convenient way to make an item draggable.
- drag.target specifies the id of the item to drag.
- drag.active specifies if the target item is currently being dragged.
- drag.axis specifies whether dragging can be done horizontally (Drag.XAxis), vertically (Drag.YAxis), or both (Drag.XAndYAxis)
- drag.minimum and drag.maximum limit how far the target can be dragged along the corresponding axes.
这是Qt文档中对于drag属性的描述,所以可以很轻松的做如下设计。
由于在对DragBar的定义上,又要响应点击又要响应拖拽,所以我把事件放在了MouseArea的released事件上,并通过判断触发该事件时的x坐标来区分这几种行为。
[关闭状态]
[打开状态]
在定义第5条中'当用DragBar组成列表后,同一时间只有一个DragBar为[打开]状态',所以我将DragBar的打开关闭状态与activefocus属性关联,当activefocus为false时,即当焦点不在该控件上时,DragBar关闭。
好像差不多就这样,具体代码如下:
//DragBar.qml
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Controls.Private 1.0
Control {
id:root
implicitWidth: parent.width
implicitHeight: 80
style: Qt.createComponent("DragBarStyle.qml", root)
property real boundary: 40 //滑动开关的边界值
property alias isOpen: dragRec.isOpen //是否打开标志 true打开 false关闭
onActiveFocusChanged: {
if (!activeFocus) {
isOpen = false
}
}
Loader {
id:backboard
property Component __bkButtons //背景图标
height: parent.height
anchors.right: parent.right
sourceComponent: __style && __style.buttons ? __style.buttons : __bkButtons
}
Loader {
id: dragRec
property Component __upPanel //上层面板
property bool isOpen: false //是否打开标志 true打开 false关闭
height: parent.height
width: parent.width
Drag.active: dragArea.drag.active
sourceComponent: __style && __style.upper ? __style.upper : __upPanel
onIsOpenChanged: {
if (isOpen) {
dropOpen.start()
}else {
dropClose.start()
}
}
PropertyAnimation on x {
id:dropOpen
running:false
to:dragArea.drag.minimumX
easing.type: Easing.InOutQuad
}
PropertyAnimation on x {
id:dropClose
running:false
to:dragArea.drag.maximumX
easing.type: Easing.InOutQuad
}
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: parent
drag.axis: Drag.XAxis
drag.maximumX: 0
drag.minimumX: -backboard.width
property real oldx
onPressed: {
oldx = mouse.x
}
onReleased: {
root.forceActiveFocus()
console.log("dragRec.x:"+dragRec.x)
if (!dragRec.isOpen) {
if (dragRec.x !== 0 && dragRec.x>-root.boundary) {
dropClose.start()
}else if (dragRec.x !== 0 || oldx===mouse.x){
dragRec.isOpen = true
}
}else {
dragRec.isOpen = false
}
}
}
}
function modifyfun(){
console.log("修改操作")
}
function deletefun() {
console.log("删除操作")
}
}
这是对应的style样式的qml:
//DragBarStyle.qml
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Controls.Private 1.0
Style {
id:style
//背景上的按钮们
property Component buttons: Row {
height: parent.height
Rectangle {
height: parent.height
width: 80
color: "#f9cdac"
Text{
anchors.centerIn: parent
text:"修改"
color: "#ffffff"
}
MouseArea {
anchors.fill: parent
onClicked: {
control.modifyfun()
}
}
}
Rectangle {
id:aaaa
height: parent.height
width: 80
color: "#fc9d9a"
Text{
anchors.centerIn: parent
text:"删除"
color: "#ffffff"
}
MouseArea {
anchors.fill: parent
onClicked: {
control.deletefun()
}
}
}
}
//上层面板样式
property Component upper: Rectangle {
anchors.fill: parent
color: "#ffffff"
Text {
anchors.centerIn: parent
text:"点一下或者拖拽就会打开"
color: "#666666"
}
}
//布局面板 可以设置底板背景颜色 不过一般看不见吧
property Component panel: Item {
anchors.fill: parent
}
}
运行效果图:
~ 这个是全关闭的状态
~ 打开上面的DragBar
~ 打开下面的DragBar,上面的自动关闭