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
}
ListModel {
id: tree_model
ListElement {
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 randomName() {
var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
return names[Math.floor(Math.random() * names.length)]
}
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{
@ -197,7 +60,17 @@ Item {
left:parent.left
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
top: parent.top
}
FluText{
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:"test"
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
property bool checked: false
property string text: "Check Box"
property var checkClicked
width: childrenRect.width
height: childrenRect.height
@ -78,6 +79,10 @@ Item {
anchors.fill: parent
hoverEnabled: true
onClicked: {
if(checkClicked){
checkClicked()
return
}
checked = !checked
}
}

View File

@ -9,253 +9,213 @@ Rectangle {
id:root
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
}
property int selectionMode: FluTreeView.None
property var currentElement
property var currentParentElement
property var multipElement: []
property var rootModel: tree_model.get(0).items
signal itemClicked(var item)
ListModel{
id:tree_model
ListElement{
text: "Root"
text: "根节点"
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:[]
}
]
}
]
}
}
Component{
id:comp_delegate
ColumnLayout{
id:layout_column
spacing: 0
id: delegate_root
Column{
width: calculateWidth()
property var itemModel: model
property int level: mapToItem(list_root,0,0).x/0.001
width: list_root.width
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{
id:delegate_items
Column{
id:item_layout
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
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{
Layout.preferredHeight: childrenRect.height
Layout.preferredWidth: childrenRect.width
id:item_layout_rect
width: list_root.contentWidth
height: item_layout_row.implicitHeight
Rectangle{
height: parent.height
width: list_root.width
anchors.fill: parent
anchors.margins: 2
radius: 4
color:{
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)
}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)
}
}
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{
id:item_layout_mouse
anchors.fill: parent
hoverEnabled: true
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{
spacing: 0
id:item_layout_row
anchors.verticalCenter: item_layout_rect.verticalCenter
Item{
width: 15*level
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{
id:item_layout_expanded
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: {
if(!item_layout.isItems){
item_layout_rect.onClickItem()
return
}
model.expanded = !model.expanded
}
}
FluText {
text:model.text
text: item_layout.text
Layout.alignment: Qt.AlignVCenter
topPadding: 10
bottomPadding: 10
}
}
}
Item{
Layout.preferredWidth: layout_column.width
Layout.preferredHeight:childrenRect.height
visible: model.expanded
ListView{
x:0.001
width: parent.width
height: childrenRect.height
model:itemModel.items
delegate:comp_delegate
boundsBehavior: ListView.StopAtBounds
id:item_sub
visible: {
if(!isItems){
return false
}
return item_layout.expanded??false
}
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
}
}
}
}
@ -264,8 +224,32 @@ Rectangle {
ListView {
id: list_root
anchors.fill: parent
delegate:comp_delegate
delegate: delegate_root
boundsBehavior: ListView.StopAtBounds
contentWidth: contentItem.childrenRect.width
model: tree_model
flickableDirection: Flickable.HorizontalAndVerticalFlick
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};
}