1、ListView的滚动条样式订制
2、基于(1、ListView的滚动条样式订制)实现一个简单的代理自定义ComboBox
3、基于(1、ListView的滚动条样式订制)实现一个复杂的代理TreeView
--------------------------------------------------------------
1、ListView的滚动条样式订制
因为 import Qt.labs.controls 1.0 的原因,会导致控件的使用和import QtQuick.Controls 1.4中的控件冲突,所以需要将订制的ListView单独封装成一个qml文件,使用的时候引入即可。
滚动条样式参考文章:http://blog.csdn.net/shado_walker/article/details/60575578
ZzListView.qml
//可以根据需求修改订制的内容
import QtQuick 2.6 //根据QT版本变化
import Qt.labs.controls 1.0
ListView {
property alias scrollBarVisible: scrollBar.visible //设置滚动条的可见性
boundsBehavior: Flickable.StopAtBounds //设置内容不能被拖动到可滑动的边界之外。
ScrollBar.vertical: ScrollBar { //订制滚动条(可以其他方式订制并绑定滑动行为)
id: scrollBar
visible: false
onActiveChanged: {
active = true;
}
Component.onCompleted: {
scrollBar.handle.color = "#33000000"; //滚动条颜色
scrollBar.active = true;
scrollBar.handle.width = 5; //滚动条宽度
}
}
}
ListView的滚动条样式订制完成。2、中可以看到使用方法。
QtQuick.Controls 1.4中ComboBox在XP系统中显示不完整
Qt.labs.controls 1.0 中ComboBox样式太丑,且无法订制Style
所以可以根据订制好的ListView中加入一个简单的代理,即可实现订制的ComboBox。
要实现ComboBox的1个效果(点击弹出框之外的区域弹框会消失),这里选用Popup来实现。
ZzComboBox.qml
import Qt.labs.controls 1.0 as Pp //as Pp 解决Qt.labs.controls 1.0和QtQuick.Controls 1.4的冲突
import QtQuick.Controls 1.4
import QtQuick 2.6
Rectangle {
id:year
anchors.centerIn: parent
border.width: 1
border.color: "lightblue"
width: 80
height: 20
Text {
anchors.verticalCenter: parent.verticalCenter
id: yearText
text: "2017"
anchors.left: parent.left
anchors.leftMargin: 5
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
year.border.color = "blue"
}
onExited: {
year.border.color = "lightblue"
}
onClicked: {
popup.open()
}
}
}
Pp.Popup {
id: popup
x: year.x
y: 20
width: 80
height: 105
closePolicy: Pp.Popup.OnEscape | Pp.Popup.OnPressOutside //单击弹窗外关闭弹窗
background: Rectangle {
color: "white"
border.color: "#bbbbbb"
border.width: 1
clip: true//防止滚动的时候内容超出边界
ZzListView {//1、中订制了滚动条的ListView
id:listv
anchors.fill: parent
anchors.margins: 2
currentIndex: 0
clip: true//防止滚动的时候内容超出边界
delegate: Rectangle {//基于1、中订制的ListView实现一个简单的代理
id:deleg
width: 253
height: 20
color: "white"
Text {
id:text
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 5
text: name
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
listv.scrollBarVisible = true//鼠标进入代理中显示滚动条
deleg.color = "lightblue"
}
onExited: {
listv.scrollBarVisible = false//鼠标离开代理后滚动条消失
deleg.color = "white"
}
onClicked: {
yearText.text = text.text
popup.close()//关闭弹窗
}
}
}
model: ListModel {
id: listModel
//model用来加载代理中显示的内容
//这个ComboBox弹窗中用来显示年,具体内容可以在model的完成事件中去设置
//如:Compenent.OnCompeneted{listModel.append({"name":"2018"})}
ListElement {name: "2013"}
ListElement {name: "2014"}
ListElement {name: "2015"}
ListElement {name: "2016"}
ListElement {name: "2017"}
}
}
}
}
这样就实现了一个订制了简单代理以及滚动条的ListView,同时也实现了一个简单ComboBox的订制。
3、基于(1、ListView的滚动条样式订制)实现一个复杂的代理
通过1、和2、可以实现ListView的样式订制和简单使用,接下来在1、的基础上实现一个复杂的代理。
自定义TreeView(QML中的TreeView中的model貌似需要在C++中实现,没花时间去研究)
这里用自定义样式的ListView去实现一个4级的树,可以根据model中的level去控制树的级数。
这里的递归组件,参考了一位大牛的文章。
地址:https://www.codeproject.com/Articles/632795/QML-TreeModel-and-TreeView
代码:
//Model
ListModel {
id: objModel
Component.onCompleted: {
objModel.append({"name":"一级节点1","level":0,"subNode":[]})
objModel.append({"name":"一级节点2","level":0,"subNode":[]})
objModel.append({"name":"一级节点3","level":0,"subNode":[]})
objModel.get(0).subNode.append({"name":"一级节点1子节点1","level":1,"subNode":[]})
objModel.get(0).subNode.append({"name":"一级节点1子节点2","level":1,"subNode":[]})
objModel.get(0).subNode.append({"isClicked":false,"name":"一级节点1子节点3","level":1,"subNode":[]})
objModel.get(0).subNode.append({"name":"一级节点1子节点4","level":1,"subNode":[]})
objModel.get(0).subNode.get(3).subNode.append({"isClicked":false,"name":"一级节点1子节点4中子节点1","level":2,"subNode":[]})
objModel.get(0).subNode.get(1).subNode.append({"isClicked":false,"name":"一级节点1子节点2中子节点1","level":2,"subNode":[]})
objModel.get(0).subNode.get(1).subNode.append({"name":"一级节点1子节点2中子节点2","level":2,"subNode":[]})
objModel.get(0).subNode.get(1).subNode.get(1).subNode.append({"isClicked":false,"name":"一级节点1子节点2中子节点2中子节点1","level":3,"subNode":[]})
objModel.get(0).subNode.get(1).subNode.get(1).subNode.append({"isClicked":false,"name":"一级节点1子节点2中子节点2中子节点2","level":3,"subNode":[]})
}
}
//Delegate
Component {
id: objRecursiveDelegate
Column {
id: objRecursiveColumn
Rectangle {
id:textBG
width: listv.width
height: 30
color: "transparent"
Image{
id: textselectBG
anchors.fill: parent
source: ""
}
Image {
id: image
width: 12
height: 12
anchors.left: parent.left
anchors.leftMargin: 0 == model.level ? 5 :
1 == model.level? 20 :
2 == model.level? 35 : 50
anchors.verticalCenter: parent.verticalCenter
source: model.isClicked ? model.imgOnClicked : model.img//model中的元素被删除了。。
}
Text {
id:tabtext
width: parent.width - 50
anchors.left: image.right
anchors.leftMargin: 5
anchors.verticalCenter: parent.verticalCenter
text: model.name
elide: Text.ElideRight
color: model.isClicked ? "#1b1b1b" : "#7d7d7d"
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
listv.scrollBarVisible = true
textselectBG.source = "qrc:/img/mainView/gm_shuxingcaidan-xuanze.png"
}
onExited: {
listv.scrollBarVisible = false
textselectBG.source = ""
}
onClicked: {
setTreeNodeColor(true, tabtext.text)
for(var i = 1; i < objRecursiveColumn.children.length - 1; ++i) {
objRecursiveColumn.children[i].visible = !objRecursiveColumn.children[i].visible
}
//setShowTab(tabtext.text)
}
}
}
Repeater {
model: subNode
delegate: objRecursiveDelegate
}
}
}
//View
ZzListView {
id:listv
anchors.fill: parent
model: objModel //关联数据模型
delegate: objRecursiveDelegate //关联代理
focus: true //可以获得焦点,这样就可以响应键盘了
}
这里根据自定义的ZzListView,通过复杂的代理,实现了TreeView。