main
朱子楚\zhuzi 2023-03-07 23:27:32 +08:00
parent 73bf9576d4
commit 8412d1fa04
3 changed files with 293 additions and 380 deletions

View File

@ -12,181 +12,44 @@ Item {
fontStyle: FluText.TitleLarge fontStyle: FluText.TitleLarge
} }
ListModel { function randomName() {
id: tree_model var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
ListElement { return names[Math.floor(Math.random() * names.length)]
text: "Root"
expanded:true
items: [
ListElement {
text: "Node 1"
expanded:false
items: [
ListElement {
text: "Node 1.1"
expanded:true
items:[
ListElement{
text:"Node 1.1.1"
expanded:true
items:[
ListElement{
text:"Node 1.1.1.1"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.2"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.3"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.4"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.5"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.6"
expanded:false
items:[]
}
]
}
]
},
ListElement {
text: "Node 1.2"
expanded:false
items:[]
}
]
},
ListElement {
text: "Node 2"
expanded:false
items:[]
},
ListElement {
text: "Node 3"
expanded:true
items: [
ListElement {
text: "Node 3.1"
expanded:false
items:[]
},
ListElement {
text: "Node 3.2"
expanded:false
items:[]
},
ListElement {
text: "Node 3.3"
expanded:false
items:[]
},
ListElement {
text: "Node 3.4"
expanded:false
items:[]
},
ListElement {
text: "Node 3.5"
expanded:false
items:[]
},
ListElement {
text: "Node 3.6"
expanded:false
items:[]
},
ListElement {
text: "Node 3.7"
expanded:false
items:[]
},
ListElement {
text: "Node 3.8"
expanded:false
items:[]
},
ListElement {
text: "Node 3.9"
expanded:false
items:[]
},
ListElement {
text: "Node 3.10"
expanded:true
items:[
ListElement{
text:"Node 3.10.1"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.2"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.3"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.4"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.5"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.6"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.7"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.8"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.9"
expanded:false
items:[]
}
]
},
ListElement {
text: "Node 3.11"
expanded:false
items:[]
}
]
}
]
}
} }
function randomCompany() {
var companies = ["阿里巴巴", "腾讯", "百度", "京东", "华为", "小米", "字节跳动", "美团", "滴滴"]
return companies[Math.floor(Math.random() * companies.length)]
}
function randomDepartment() {
var departments = ["技术部", "销售部", "市场部", "人事部", "财务部", "客服部", "产品部", "设计部", "运营部"]
return departments[Math.floor(Math.random() * departments.length)]
}
function createEmployee() {
var name = randomName()
return tree_view.createItem(name, false)
}
function createSubtree(numEmployees) {
var employees = []
for (var i = 0; i < numEmployees; i++) {
employees.push(createEmployee())
}
return tree_view.createItem(randomDepartment(), true, employees)
}
function createOrg(numLevels, numSubtrees, numEmployees) {
if (numLevels === 0) {
return []
}
var subtrees = []
for (var i = 0; i < numSubtrees; i++) {
subtrees.push(createSubtree(numEmployees))
}
return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees))
}
FluTreeView{ FluTreeView{
@ -197,7 +60,17 @@ Item {
left:parent.left left:parent.left
bottom:parent.bottom bottom:parent.bottom
} }
model:tree_model onItemClicked:
(model)=>{
showSuccess(model.text)
}
Component.onCompleted: {
var org = createOrg(10, 3, 5)
updateData(org)
}
} }
@ -207,11 +80,62 @@ Item {
right: parent.right right: parent.right
top: parent.top top: parent.top
} }
FluButton{
text:"test" FluText{
onClicked: { text:{
if(tree_view.selectionMode === FluTreeView.None){
return "FluTreeView.None"
}
if(tree_view.selectionMode === FluTreeView.Single){
return "FluTreeView.Single"
}
if(tree_view.selectionMode === FluTreeView.Multiple){
return "FluTreeView.Multiple"
}
} }
} }
}
FluButton{
text:"None"
onClicked: {
tree_view.selectionMode = FluTreeView.None
}
}
FluButton{
text:"Single"
onClicked: {
tree_view.selectionMode = FluTreeView.Single
}
}
FluButton{
text:"Multiple"
onClicked: {
tree_view.selectionMode = FluTreeView.Multiple
}
}
FluFilledButton{
text:"获取选中的数据"
onClicked: {
if(tree_view.selectionMode === FluTreeView.None){
showError("当前非选择模式,没有选中的数据")
}
if(tree_view.selectionMode === FluTreeView.Single){
showSuccess(tree_view.signleData().text)
}
if(tree_view.selectionMode === FluTreeView.Multiple){
if(tree_view.multipData().length===0){
showError("没有选中数据")
return
}
var info = []
tree_view.multipData().map((value)=>info.push(value.text))
showSuccess(info.join(","))
}
}
}
}
} }

View File

@ -7,6 +7,7 @@ Item {
id:root id:root
property bool checked: false property bool checked: false
property string text: "Check Box" property string text: "Check Box"
property var checkClicked
width: childrenRect.width width: childrenRect.width
height: childrenRect.height height: childrenRect.height
@ -78,6 +79,10 @@ Item {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: { onClicked: {
if(checkClicked){
checkClicked()
return
}
checked = !checked checked = !checked
} }
} }

View File

@ -9,263 +9,247 @@ Rectangle {
id:root id:root
color: FluTheme.isDark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(253/255,253/255,253/255,1) color: FluTheme.isDark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(253/255,253/255,253/255,1)
property alias model: list_root.model enum TreeViewSelectionMode {
None,
Single,
Multiple
}
ListModel { property int selectionMode: FluTreeView.None
id: tree_model
ListElement { property var currentElement
text: "Root" property var currentParentElement
property var multipElement: []
property var rootModel: tree_model.get(0).items
signal itemClicked(var item)
ListModel{
id:tree_model
ListElement{
text: "根节点"
expanded:true expanded:true
items: [ items:[]
ListElement {
text: "Node 1"
expanded:false
items: [
ListElement {
text: "Node 1.1"
expanded:true
items:[
ListElement{
text:"Node 1.1.1"
expanded:true
items:[
ListElement{
text:"Node 1.1.1.1"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.2"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.3"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.4"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.5"
expanded:false
items:[]
},
ListElement{
text:"Node 1.1.1.6"
expanded:false
items:[]
}
]
}
]
},
ListElement {
text: "Node 1.2"
expanded:false
items:[]
}
]
},
ListElement {
text: "Node 2"
expanded:false
items:[]
},
ListElement {
text: "Node 3"
expanded:true
items: [
ListElement {
text: "Node 3.1"
expanded:false
items:[]
},
ListElement {
text: "Node 3.2"
expanded:false
items:[]
},
ListElement {
text: "Node 3.3"
expanded:false
items:[]
},
ListElement {
text: "Node 3.4"
expanded:false
items:[]
},
ListElement {
text: "Node 3.5"
expanded:false
items:[]
},
ListElement {
text: "Node 3.6"
expanded:false
items:[]
},
ListElement {
text: "Node 3.7"
expanded:false
items:[]
},
ListElement {
text: "Node 3.8"
expanded:false
items:[]
},
ListElement {
text: "Node 3.9"
expanded:false
items:[]
},
ListElement {
text: "Node 3.10"
expanded:true
items:[
ListElement{
text:"Node 3.10.1"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.2"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.3"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.4"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.5"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.6"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.7"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.8"
expanded:false
items:[]
},
ListElement{
text:"Node 3.10.9"
expanded:false
items:[]
}
]
},
ListElement {
text: "Node 3.11"
expanded:false
items:[]
}
]
}
]
} }
} }
Component{
id: delegate_root
Column{
width: calculateWidth()
property var itemModel: model
Repeater{
id: repeater_first_level
model: items
delegate: delegate_items
}
function calculateWidth(){
var w = 0;
for(var i = 0; i < repeater_first_level.count; i++) {
var child = repeater_first_level.itemAt(i)
if(w < child.width_hint){
w = child.width_hint;
}
}
return w;
}
}
}
Component{ Component{
id:comp_delegate id:delegate_items
ColumnLayout{ Column{
id:layout_column id:item_layout
spacing: 0
property real level: (mapToItem(list_root,0,0).x+list_root.contentX)/0.001
property var text: model.text??"Item"
property bool isItems : (model.items !== undefined) && (model.items.count !== 0)
property var items: model.items??[]
property var expanded: model.expanded??true
property int width_hint: calculateWidth()
property bool singleSelected: currentElement === model
property var itemModel: model property var itemModel: model
property int level: mapToItem(list_root,0,0).x/0.001
width: list_root.width function calculateWidth(){
var w = Math.max(list_root.width, item_layout_row.implicitWidth + 10);
if(expanded){
for(var i = 0; i < repeater_items.count; i++) {
var child = repeater_items.itemAt(i)
if(w < child.width_hint){
w = child.width_hint;
}
}
}
return w;
}
Item{ Item{
Layout.preferredHeight: childrenRect.height id:item_layout_rect
Layout.preferredWidth: childrenRect.width width: list_root.contentWidth
height: item_layout_row.implicitHeight
Rectangle{ Rectangle{
height: parent.height anchors.fill: parent
width: list_root.width
anchors.margins: 2 anchors.margins: 2
radius: 4
color:{ color:{
if(FluTheme.isDark){ if(FluTheme.isDark){
if(item_layout.singleSelected && selectionMode === FluTreeView.Single){
return Qt.rgba(62/255,62/255,62/255,1)
}
return (item_layout_mouse.containsMouse || item_layout_expanded.hovered)?Qt.rgba(62/255,62/255,62/255,1):Qt.rgba(50/255,50/255,50/255,1) return (item_layout_mouse.containsMouse || item_layout_expanded.hovered)?Qt.rgba(62/255,62/255,62/255,1):Qt.rgba(50/255,50/255,50/255,1)
}else{ }else{
if(item_layout.singleSelected && selectionMode === FluTreeView.Single){
return Qt.rgba(244/255,244/255,244/255,1)
}
return (item_layout_mouse.containsMouse || item_layout_expanded.hovered)?Qt.rgba(244/255,244/255,244/255,1):Qt.rgba(253/255,253/255,253/255,1) return (item_layout_mouse.containsMouse || item_layout_expanded.hovered)?Qt.rgba(244/255,244/255,244/255,1):Qt.rgba(253/255,253/255,253/255,1)
} }
} }
Rectangle{
width: 3
color:FluTheme.primaryColor.dark
visible: item_layout.singleSelected && (selectionMode === FluTreeView.Single)
radius: 3
height: 20
anchors{
left: parent.left
verticalCenter: parent.verticalCenter
}
}
MouseArea{ MouseArea{
id:item_layout_mouse id:item_layout_mouse
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: { onClicked: {
console.debug("---------") item_layout_rect.onClickItem()
} }
} }
} }
function onClickItem(){
if(selectionMode === FluTreeView.None){
itemClicked(model)
}
if(selectionMode === FluTreeView.Single){
currentElement = model
if(item_layout.parent.parent.parent.itemModel){
currentParentElement = item_layout.parent.parent.parent.itemModel
}else{
if(item_layout.parent.itemModel){
currentParentElement = item_layout.parent.itemModel
}
}
}
if(selectionMode === FluTreeView.Multiple){
}
}
RowLayout{ RowLayout{
spacing: 0 id:item_layout_row
anchors.verticalCenter: item_layout_rect.verticalCenter
Item{ Item{
width: 15*level width: 15*level
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
FluCheckBox{
text:""
checked: multipElement.includes(itemModel)
visible: selectionMode === FluTreeView.Multiple
checkClicked:function(){
if(checked){
multipElement = multipElement.filter((value) => value !== itemModel)
}else{
multipElement = [...multipElement,itemModel]
}
}
}
FluIconButton{ FluIconButton{
id:item_layout_expanded id:item_layout_expanded
color:"#00000000" color:"#00000000"
icon:model.expanded?FluentIcons.FA_angle_down:FluentIcons.FA_angle_right icon:item_layout.expanded?FluentIcons.FA_angle_down:FluentIcons.FA_angle_right
opacity: item_layout.isItems
onClicked: { onClicked: {
if(!item_layout.isItems){
item_layout_rect.onClickItem()
return
}
model.expanded = !model.expanded model.expanded = !model.expanded
} }
} }
FluText{
text:model.text FluText {
text: item_layout.text
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
topPadding: 10
bottomPadding: 10
} }
} }
} }
Item{ Item{
Layout.preferredWidth: layout_column.width id:item_sub
Layout.preferredHeight:childrenRect.height visible: {
visible: model.expanded if(!isItems){
ListView{ return false
x:0.001 }
width: parent.width return item_layout.expanded??false
height: childrenRect.height
model:itemModel.items
delegate:comp_delegate
boundsBehavior: ListView.StopAtBounds
} }
width: item_sub_layout.implicitWidth
height: item_sub_layout.implicitHeight
x:0.001
Column{
id: item_sub_layout
Repeater{
id:repeater_items
model: item_layout.items
delegate: delegate_items
}
}
} }
} }
} }
ListView{ ListView {
id:list_root id: list_root
anchors.fill: parent anchors.fill: parent
delegate:comp_delegate delegate: delegate_root
boundsBehavior: ListView.StopAtBounds
contentWidth: contentItem.childrenRect.width
model: tree_model
flickableDirection: Flickable.HorizontalAndVerticalFlick
clip: true clip: true
ScrollBar.vertical: ScrollBar { }
ScrollBar.horizontal: ScrollBar { }
}
function updateData(items){
rootModel.clear()
rootModel.append(items)
}
function signleData(){
return currentElement
}
function multipData(){
return multipElement
}
function createItem(text="Title",expanded=true,items=[]){
return {text:text,expanded:expanded,items:items};
} }