This commit is contained in:
zhuzichu 2023-06-20 18:32:10 +08:00
parent b442696f92
commit 98d73eb6cb
9 changed files with 245 additions and 585 deletions

View File

@ -20,7 +20,7 @@ endif()
file(TO_CMAKE_PATH "/" PATH_SEPARATOR) file(TO_CMAKE_PATH "/" PATH_SEPARATOR)
# #
add_definitions(-DVERSION=1,3,5,1) add_definitions(-DVERSION=1,3,6)
find_package(Qt6 REQUIRED COMPONENTS Quick) find_package(Qt6 REQUIRED COMPONENTS Quick)
qt_standard_project_setup() qt_standard_project_setup()

View File

@ -131,7 +131,8 @@ FluExpander{
"FluCopyableText", "FluCopyableText",
"FluAcrylic", "FluAcrylic",
"FluRemoteLoader", "FluRemoteLoader",
"FluMenuBar" "FluMenuBar",
"FluPagination"
]; ];
code = code.replace(/\n/g, "<br>"); code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;"); code = code.replace(/ /g, "&nbsp;");

View File

@ -259,9 +259,9 @@ FluObject{
} }
} }
FluPaneItem{ FluPaneItem{
title:"TableView2" title:"Pagination"
onTap:{ onTap:{
navigationView.push("qrc:/example/qml/page/T_TableView2.qml") navigationView.push("qrc:/example/qml/page/T_Pagination.qml")
} }
} }
FluPaneItem{ FluPaneItem{

View File

@ -0,0 +1,49 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import "qrc:///example/qml/component"
import FluentUI
FluScrollablePage{
title:"Pagination"
FluArea{
Layout.fillWidth: true
height: 200
paddings: 10
Layout.topMargin: 20
ColumnLayout{
spacing: 20
anchors.verticalCenter: parent.verticalCenter
FluPagination{
pageCurrent: 1
pageButtonCount: 5
itemCount: 5000
}
FluPagination{
pageCurrent: 2
itemCount: 5000
pageButtonCount: 7
}
FluPagination{
pageCurrent: 3
itemCount: 5000
pageButtonCount: 9
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluPagination{
pageCurrent: 1
itemCount: 1000
pageButtonCount: 9
}'
}
}

View File

@ -5,162 +5,12 @@ import QtQuick.Window
import FluentUI import FluentUI
import "qrc:///example/qml/component" import "qrc:///example/qml/component"
FluScrollablePage{ FluContentPage{
title:"TableView" title:"TableView"
Component.onCompleted: { Component.onCompleted: {
const columns = [ loadData(1,2000)
{
title: '姓名',
dataIndex: 'name',
width:100,
},
{
title: '年龄',
dataIndex: 'item_age',
width:100,
minimumWidth:100
},
{
title: '住址',
dataIndex: 'address',
width:200
},
{
title: '别名',
dataIndex: 'nickname',
width:100
},
{
title: '操作',
dataIndex: 'action',
width:120
},
];
table_view.columns = columns
loadData(1,10)
}
Component{
id:com_age
Item{
id:item_age
property var ageArr: [100,300,500,1000]
height: 60
FluComboBox{
width: 80
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 10
}
model: ListModel {
ListElement { text: 100 }
ListElement { text: 300 }
ListElement { text: 500 }
ListElement { text: 1000 }
}
Component.onCompleted: {
currentIndex=ageArr.findIndex((element) => element === dataModel.age)
}
}
}
}
Component{
id:com_action
Item{
height: 60
Row{
anchors.centerIn: parent
spacing: 10
FluFilledButton{
text:"编辑"
horizontalPadding: 6
onClicked:{
showError(JSON.stringify(dataObject))
}
}
FluFilledButton{
text:"删除"
horizontalPadding: 6
onClicked:{
tableView.remove(dataModel.index)
}
}
}
}
}
FluText{
Layout.topMargin: 20
text:"此TableView适用于小数据量带分页的表格大数据量请使用TableView2。"
}
FluTableView{
id:table_view
Layout.fillWidth: true
Layout.topMargin: 20
pageCurrent:1
pageCount:10
itemCount: 1000
onRequestPage:
(page,count)=> {
loadData(page,count)
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: 10
code:'FluTableView{
id:table_view
Layout.fillWidth: true
Layout.topMargin: 20
pageCurrent:1
pageCount:10
itemCount: 1000
onRequestPage:
(page,count)=> {
loadData(page,count)
}
Component.onCompleted: {
const columns = [
{
title: "姓名",
dataIndex: "name",
width:100
},
{
title: "年龄",
dataIndex: "age",
width:100
},
{
title: "住址",
dataIndex: "address",
width:200
},
{
title: "别名",
dataIndex: "nickname",
width:100
}
];
table_view.columns = columns
const dataSource = [
{
name: ",
age: 500,
address:"钟灵毓秀的花果山,如神仙仙境的水帘洞",
nickname:"齐天大圣"
}
];
table_view.dataSource = columns
}
}'
} }
function loadData(page,count){ function loadData(page,count){
@ -188,13 +38,68 @@ FluScrollablePage{
for(var i=0;i<count;i++){ for(var i=0;i<count;i++){
dataSource.push({ dataSource.push({
name: getRandomName(), name: getRandomName(),
item_age: com_age,
age:getRandomAge(), age:getRandomAge(),
address: getRandomAddresses(), address: getRandomAddresses(),
nickname: getRandomNickname(), nickname: getRandomNickname()
action:com_action
}) })
} }
table_view.dataSource = dataSource table_view.dataSource = dataSource
} }
Component{
id:com_combobox
FluComboBox {
anchors.fill: parent
currentIndex: display
editable: true
model: ListModel {
ListElement { text: 100 }
ListElement { text: 300 }
ListElement { text: 500 }
ListElement { text: 1000 }
}
Component.onCompleted: {
currentIndex=[100,300,500,1000].findIndex((element) => element === Number(display))
selectAll()
}
TableView.onCommit: {
display = editText
}
}
}
FluTableView{
id:table_view
anchors.fill: parent
anchors.topMargin: 20
columnSource:[
{
title: '姓名',
dataIndex: 'name',
width:100,
minimumWidth:50
},
{
title: '年龄',
dataIndex: 'age',
editDelegate:com_combobox,
width:100,
minimumWidth:100,
maximumWidth: 100
},
{
title: '住址',
dataIndex: 'address',
width:200
},
{
title: '别名',
dataIndex: 'nickname',
width:100,
}
]
}
} }

View File

@ -13,7 +13,7 @@ endif()
set(QML_PLUGIN_DIRECTORY ${CMAKE_PREFIX_PATH}/qml/FluentUI) set(QML_PLUGIN_DIRECTORY ${CMAKE_PREFIX_PATH}/qml/FluentUI)
# #
add_definitions(-DVERSION=1,3,5,1) add_definitions(-DVERSION=1,3,6)
find_package(Qt6 REQUIRED COMPONENTS Core Quick Qml) find_package(Qt6 REQUIRED COMPONENTS Core Quick Qml)
qt_standard_project_setup() qt_standard_project_setup()

View File

@ -9,9 +9,9 @@ Item {
property string nextText: "下一页>" property string nextText: "下一页>"
property int pageCurrent: 0 property int pageCurrent: 0
property int itemCount: 0 property int itemCount: 0
property int pageButtonCount: 5
property int pageCount: itemCount>0?Math.ceil(itemCount/__itemPerPage):0 property int pageCount: itemCount>0?Math.ceil(itemCount/__itemPerPage):0
property int __itemPerPage: 10 property int __itemPerPage: 10
property int pageButtonCount: 5
property int __pageButtonHalf: Math.floor(pageButtonCount/2)+1 property int __pageButtonHalf: Math.floor(pageButtonCount/2)+1
id: control id: control
implicitHeight: 40 implicitHeight: 40
@ -34,7 +34,6 @@ Item {
FluToggleButton{ FluToggleButton{
property int pageNumber:1 property int pageNumber:1
visible: control.pageCount>0 visible: control.pageCount>0
enabled: control.pageCurrent>1
checked: pageNumber === control.pageCurrent checked: pageNumber === control.pageCurrent
text:String(pageNumber) text:String(pageNumber)
clickListener:function() { clickListener:function() {

View File

@ -2,293 +2,163 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Controls.Basic import QtQuick.Controls.Basic
import QtQuick.Layouts import QtQuick.Layouts
import Qt.labs.qmlmodels
import FluentUI import FluentUI
Item { Rectangle {
property var columns : [] property var columnSource
property var dataSource : [] property var dataSource
property int pageCurrent: 1
property int itemCount: 1000
property int pageCount: 10
property int itemHeight: 56
property bool pageVisible: true
signal requestPage(int page,int count)
id:control id:control
implicitHeight: layout_table.height color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
QtObject{ onColumnSourceChanged: {
id:d if(columnSource.length!==0){
property int columnsWidth: layout_table.headerItem.columnsWidth() var com_column = Qt.createComponent("FluTableModelColumn.qml")
if (com_column.status === Component.Ready) {
var columns= []
columnSource.forEach(function(item){
var column = com_column.createObject(table_model,{display:item.dataIndex});
columns.push(column)
})
table_model.columns = columns
} }
MouseArea{ }
}
onDataSourceChanged: {
table_model.clear()
dataSource.forEach(function(item){
table_model.appendRow(item)
})
}
TableModel {
id:table_model
}
Component{
id:com_edit
FluTextBox {
anchors.fill: parent anchors.fill: parent
preventStealing: true text: display
verticalAlignment: TextInput.AlignVCenter
Component.onCompleted: selectAll()
TableView.onCommit: {
display = text
} }
}
}
ScrollView{
id:scroll_table
anchors.left: header_vertical.right
anchors.top: header_horizontal.bottom
anchors.right: parent.right
anchors.bottom: parent.bottom
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
TableView {
id:table_view
ListModel{ ListModel{
id:model_columns id:model_columns
} }
ListModel{ boundsBehavior: Flickable.StopAtBounds
id:model_data_source ScrollBar.horizontal: FluScrollBar{}
ScrollBar.vertical: FluScrollBar{}
selectionModel: ItemSelectionModel {}
columnWidthProvider: function(column) {
let w = explicitColumnWidth(column)
if (w >= 0){
var minimumWidth = columnSource[column].minimumWidth
var maximumWidth = columnSource[column].maximumWidth
if(!minimumWidth){
minimumWidth = 100
} }
onColumnsChanged: { if(!maximumWidth){
model_columns.clear() maximumWidth = 65535
model_columns.append(columns)
} }
onDataSourceChanged: {
model_data_source.clear() return Math.min(Math.max(minimumWidth, w),maximumWidth)
model_data_source.append(dataSource)
} }
Component{ return implicitColumnWidth(column)
id:header_columns
FluRectangle{
id:layout_columns
height: control.itemHeight
width: parent.width
color:FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1)
radius: [5,5,0,0]
function columnsWidth(){
var w = 0
for(var i=0;i<repeater_columns.count;i++){
var item = repeater_columns.itemAt(i)
w=w+item.width
} }
return w rowHeightProvider: function(row) {
let h = explicitRowHeight(row)
if (h >= 0){
return Math.max(40, h)
} }
function widthByColumnIndex(index){ return implicitRowHeight(row)
return repeater_columns.itemAt(index).width
} }
Row{ model: table_model
id:list_columns
spacing: 0
anchors.fill: parent
Repeater{
id:repeater_columns
model: model_columns
delegate: Item{
id:item_column
property point clickPos: "0,0"
height: list_columns.height
width: model.width
FluText{
id:item_column_text
text:model.title
wrapMode: Text.WordWrap
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 14
}
font: FluTextStyle.BodyStrong
}
FluDivider{
id:item_divider
width: 1
height: 40
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
visible: index !== model_columns.count-1
}
MouseArea{
height: 40
width: 6
anchors.centerIn: item_divider
visible: item_divider.visible
cursorShape: Qt.SplitHCursor
onPressed:
(mouse)=>{
clickPos = Qt.point(mouse.x, mouse.y)
}
preventStealing: true
onPositionChanged:
(mouse)=>{
var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
var minimumWidth = item_column_text.implicitWidth+28
if(model.minimumWidth){
minimumWidth = model.minimumWidth
}
item_column.width = Math.max(item_column.width+delta.x,minimumWidth)
}
}
}
}
}
}
}
Flickable{
id:layout_flickable
height: layout_table.height
anchors{
top: parent.top
left: parent.left
right: parent.right
}
contentWidth: layout_table.width
clip:true
ScrollBar.horizontal: FluScrollBar {
}
Rectangle{
anchors.fill: layout_table
radius: 5
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
}
ListView{
id:layout_table
height: contentHeight
width: Math.max(layout_flickable.width,d.columnsWidth)
clip:true
interactive: false
removeDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 167 }
}
header: header_columns
footer: Item{
height: pageVisible ? 54 : 0
clip: true clip: true
width: layout_table.width delegate: Rectangle {
FluPagination{ required property bool selected
id:pagination required property bool current
height: 40 color: selected ? FluTheme.primaryColor.lightest: (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06))
pageCurrent: control.pageCurrent implicitHeight: 40
onPageCurrentChanged: control.pageCurrent = pageCurrent implicitWidth: columnSource[column].width
itemCount: control.itemCount FluText {
pageCount: control.pageCount text: display
onRequestPage:
(page,count)=> {
control.requestPage(page,count)
}
anchors{
top: parent.top
right: parent.right
}
Connections{
target: control
function onPageCurrentChanged(){
if (control.pageCurrent!==pagination.pageCurrent)
{
pagination.calcNewPage(control.pageCurrent)
}
}
}
}
}
model:model_data_source
delegate: Control{
id:item_control
height: maxHeight()
width: layout_table.width
property var model_values : getObjectValues(index)
property var itemObject: getObject(index)
property var listModel: model
Rectangle{
anchors.fill: parent anchors.fill: parent
color: { anchors.margins: 10
if(item_control.hovered){ elide: Text.ElideRight
return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) verticalAlignment: Text.AlignVCenter
} }
return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1) TableView.editDelegate: {
var obj =columnSource[column].editDelegate
if(obj){
return obj
} }
} return com_edit
FluDivider{
id:item_divider
width: parent.width
height: 1
anchors.right: parent.right
anchors.bottom: parent.bottom
}
Row{
id: table_row
spacing: 0
anchors.fill: parent
Repeater{
id:repeater_rows
model: model_values
delegate:FluControl{
id:item_row_control
width: layout_table.headerItem.widthByColumnIndex(index)
height: item_control.height
focusPolicy:Qt.TabFocus
background: Item{
FluFocusRectangle{
visible: item_row_control.activeFocus
radius:8
}
}
Loader{
id:item_column_loader
property var model : modelData
property var dataModel : listModel
property var dataObject : itemObject
property var tableView : control
anchors.verticalCenter: parent.verticalCenter
width: parent.width
sourceComponent: {
if(model.itemData instanceof Component){
return model.itemData
}
return com_text
}
}
function columnHeight(){
return item_column_loader.item.height
}
}
}
}
function maxHeight(){
var h = 0
for(var i=0;i<repeater_rows.count;i++){
var item = repeater_rows.itemAt(i)
h=Math.max(h,item.columnHeight())
}
return h
} }
} }
} }
} }
Component{ Component{
id:com_text id:com_handle
Item{ FluControl {
height: table_value.implicitHeight + 20 width: 24
FluCopyableText{ height: 24
id:table_value background: Rectangle{
text:String(model.itemData) radius: 12
width: Math.min(parent.width - 14,implicitWidth) color: FluTheme.dark ? Qt.rgba(69/255,69/255,69/255,1) :Qt.rgba(1,1,1,1)
wrapMode: Text.WordWrap
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 14
} }
rightPadding: 14 visible: SelectionRectangle.control.active
MouseArea{ FluShadow{
id:item_mouse radius: 12
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.IBeamCursor
acceptedButtons: Qt.NoButton
} }
FluTooltip{ Rectangle{
visible: item_mouse.containsMouse width: 24
text:parent.text height: 24
delay: 1000 radius: 12
scale: pressed?4/10:hovered?6/10:5/10
color:FluTheme.dark ? FluTheme.primaryColor.lighter :FluTheme.primaryColor.dark
anchors.centerIn: parent
Behavior on scale {
NumberAnimation{
duration: 167
} }
} }
} }
} }
function getObject(index){
return model_data_source.get(index)
} }
function getObjectValues(index) { SelectionRectangle {
var obj = model_data_source.get(index) target: table_view
if(!obj) bottomRightHandle:com_handle
return topLeftHandle: com_handle
var data = []
for(var i=0;i<model_columns.count;i++){
var item = model_columns.get(i)
data.push({itemData:obj[item.dataIndex],width:item.width})
} }
return data; FluHorizontalHeaderView {
id: header_horizontal
textRole: "title"
model: columnSource
anchors.left: scroll_table.left
anchors.top: parent.top
syncView: table_view
boundsBehavior: Flickable.StopAtBounds
clip: true
} }
function remove(index){ FluVerticalHeaderView {
model_data_source.remove(index) id: header_vertical
boundsBehavior: Flickable.StopAtBounds
anchors.top: scroll_table.top
anchors.left: parent.left
syncView: table_view
clip: true
} }
} }

View File

@ -1,164 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Layouts
import Qt.labs.qmlmodels
import FluentUI
Rectangle {
property var columnSource
property var dataSource
id:control
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
onColumnSourceChanged: {
if(columnSource.length!==0){
var com_column = Qt.createComponent("FluTableModelColumn.qml")
if (com_column.status === Component.Ready) {
var columns= []
columnSource.forEach(function(item){
var column = com_column.createObject(table_model,{display:item.dataIndex});
columns.push(column)
})
table_model.columns = columns
}
}
}
onDataSourceChanged: {
table_model.clear()
dataSource.forEach(function(item){
table_model.appendRow(item)
})
}
TableModel {
id:table_model
}
Component{
id:com_edit
FluTextBox {
anchors.fill: parent
text: display
verticalAlignment: TextInput.AlignVCenter
Component.onCompleted: selectAll()
TableView.onCommit: {
display = text
}
}
}
ScrollView{
id:scroll_table
anchors.left: header_vertical.right
anchors.top: header_horizontal.bottom
anchors.right: parent.right
anchors.bottom: parent.bottom
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
TableView {
id:table_view
ListModel{
id:model_columns
}
boundsBehavior: Flickable.StopAtBounds
ScrollBar.horizontal: FluScrollBar{}
ScrollBar.vertical: FluScrollBar{}
selectionModel: ItemSelectionModel {}
columnWidthProvider: function(column) {
let w = explicitColumnWidth(column)
if (w >= 0){
var minimumWidth = columnSource[column].minimumWidth
var maximumWidth = columnSource[column].maximumWidth
if(!minimumWidth){
minimumWidth = 100
}
if(!maximumWidth){
maximumWidth = 65535
}
return Math.min(Math.max(minimumWidth, w),maximumWidth)
}
return implicitColumnWidth(column)
}
rowHeightProvider: function(row) {
let h = explicitRowHeight(row)
if (h >= 0){
return Math.max(40, h)
}
return implicitRowHeight(row)
}
model: table_model
clip: true
delegate: Rectangle {
required property bool selected
required property bool current
color: selected ? FluTheme.primaryColor.lightest: (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06))
implicitHeight: 40
implicitWidth: columnSource[column].width
FluText {
text: display
anchors.fill: parent
anchors.margins: 10
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
TableView.editDelegate: {
var obj =columnSource[column].editDelegate
if(obj){
return obj
}
return com_edit
}
}
}
}
Component{
id:com_handle
FluControl {
width: 24
height: 24
background: Rectangle{
radius: 12
color: FluTheme.dark ? Qt.rgba(69/255,69/255,69/255,1) :Qt.rgba(1,1,1,1)
}
visible: SelectionRectangle.control.active
FluShadow{
radius: 12
}
Rectangle{
width: 24
height: 24
radius: 12
scale: pressed?4/10:hovered?6/10:5/10
color:FluTheme.dark ? FluTheme.primaryColor.lighter :FluTheme.primaryColor.dark
anchors.centerIn: parent
Behavior on scale {
NumberAnimation{
duration: 167
}
}
}
}
}
SelectionRectangle {
target: table_view
bottomRightHandle:com_handle
topLeftHandle: com_handle
}
FluHorizontalHeaderView {
id: header_horizontal
textRole: "title"
model: columnSource
anchors.left: scroll_table.left
anchors.top: parent.top
syncView: table_view
boundsBehavior: Flickable.StopAtBounds
clip: true
}
FluVerticalHeaderView {
id: header_vertical
boundsBehavior: Flickable.StopAtBounds
anchors.top: scroll_table.top
anchors.left: parent.left
syncView: table_view
clip: true
}
}