QML TableView滚动条无法拉到底及显示逻辑问题求助
QML TableView滚动条无法拉到底部问题修复
问题描述
我编写的QML TableView包含40行数据,但滚动条无法拉到底部,且最大滚动位置会随行数变化。需求如下:
- 无论行数多少,滚动条都能从顶部滚动到底部
- 打开表格默认显示前11行,行数>11时显示滚动条,行数<11时隐藏滚动条
原代码
TableView { id: tableView anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.top: parent.top anchors.topMargin: 115 anchors.bottomMargin: 85 anchors.rightMargin: 55 anchors.leftMargin: 55 backgroundVisible: false clip: true verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn horizontalScrollBarPolicy: horizontalScrollBar; flickableItem.flickableDirection : Flickable.HorizontalAndVerticalFlick property int rowHeight: scrMgr.size.height * 40 / 1080 property int startYContent: 0 property int topYcontent: tableView.flickableItem.contentY property int topRow: topYcontent + tableView.rowAt(5,tableView.startYContent + 5) - topYcontent //keep add and substract in order to have active bindings onTopRowChanged: { console.log("topRoww: " + topRow); } resources: { var length = columns.length var temp = [] for(var i = 0; i < length; i++) { temp.push(columnComponent.createObject(tableView, {"role": columns[i].role, "title": columns[i].title})); } return temp } model: scancardimg.model style: TableViewStyle { incrementControl: Rectangle { visible: false } decrementControl: Rectangle { visible: false } handle: Rectangle { x:0 y:0 color: "transparent" border.color: "transparent" CustomImage { source: resMgr.getResource("qrc:/Images/Slider/Sliderdot.svg") implicitWidth: scrMgr.size.width * 0.0364//35 implicitHeight: implicitWidth utilBox {t_left: 20; t_right: 20; t_top: 18; t_bottom: 22;} Rectangle { anchors.fill: parent; color: "#00000000"; border.color: "yellow"; border.width: 1;} } } scrollBarBackground: Rectangle { id: control implicitWidth: scrMgr.size.width * 0.0364 //35 color: "transparent" border.color: "transparent" CustomImage { source: resMgr.getResource("qrc:/Images/Slider/Sliderbar.svg") anchors.fill: parent utilBox {t_left: 0; t_right: 0; t_top: 2.3; t_bottom: 5;} Rectangle { anchors.fill: parent; color: "#00000000"; border.color: "yellow"; border.width: 1;} } } frame: Rectangle { color: "#00000000" border.color: "#00000000" } alternateBackgroundColor: "#00000000" itemDelegate: Item { x: scrMgr.size.width * 0.0084 //8 y: scrMgr.size.width * 0.002 //8 height: tableView.rowHeight //19 Text { anchors.verticalCenter: parent.verticalCenter anchors.fill: parent color: styleData.textColor elide: styleData.elideMode text: styleData.value font.pixelSize: scrMgr.size.height * 0.028 visible: tableView.topRow >= 0 ? (styleData.row >= tableView.topRow) : true } } rowDelegate: Rectangle{ width: childrenRect.width height: tableView.rowHeight color: "#00000000"; } headerDelegate: Rectangle { id: headerComp height: textItem.implicitHeight * 1.2 + scrMgr.size.height * 0.0277 //15 width: textItem.implicitWidth color: "#00000000"; Text { id: textItem anchors.fill: parent font.pixelSize: scrMgr.size.height * 0.028 verticalAlignment: Text.AlignVCenter horizontalAlignment: styleData.textAlignment anchors.leftMargin: scrMgr.size.width * 0.0084 //8 anchors.topMargin: scrMgr.size.height * 0.015 //8 text: styleData.value color: "white" } Component.onCompleted: { tableView.startYContent = headerComp.y + headerComp.height; } } } }
滚动条效果
滚动条滑块无法移动到滚动条底部,无法显示表格最后几行。
修复方案
1. 动态控制滚动条显示
将verticalScrollBarPolicy改为根据行数动态判断:
verticalScrollBarPolicy: model.rowCount > 11 ? Qt.ScrollBarAsNeeded : Qt.ScrollBarAlwaysOff
2. 简化可见行计算逻辑
原topRow的绑定逻辑过于复杂,容易干扰TableView内部的滚动范围计算,改用内置属性替代:
// 移除原topYcontent、topRow定义,替换为: property int topRow: Math.floor(flickableItem.visibleArea.yPosition * model.rowCount)
3. 修正滚动条样式的尺寸适配
自定义滚动条handle的固定尺寸可能导致滚动范围计算错误,改为相对父元素尺寸:
handle: Rectangle { color: "transparent" border.color: "transparent" CustomImage { source: resMgr.getResource("qrc:/Images/Slider/Sliderdot.svg") width: parent.width height: width utilBox {t_left: 20; t_right: 20; t_top: 18; t_bottom: 22;} } }
4. 修正header位置绑定时机
将startYContent改为绑定到header组件的位置,避免初始化时机问题:
property int startYContent: headerComp.y + headerComp.height // 移除headerDelegate中的Component.onCompleted赋值代码
5. 确保内容高度计算正确
TableView默认会根据rowHeight和model.rowCount自动计算flickableItem.contentHeight,不要手动修改该值,确保clip属性保持true以正确裁剪内容。
修改后的核心代码片段
TableView { id: tableView // ... 其他锚点设置不变 backgroundVisible: false clip: true verticalScrollBarPolicy: model.rowCount > 11 ? Qt.ScrollBarAsNeeded : Qt.ScrollBarAlwaysOff horizontalScrollBarPolicy: horizontalScrollBar; flickableItem.flickableDirection : Flickable.HorizontalAndVerticalFlick property int rowHeight: scrMgr.size.height * 40 / 1080 property int startYContent: headerComp.y + headerComp.height property int topRow: Math.floor(flickableItem.visibleArea.yPosition * model.rowCount) onTopRowChanged: { console.log("topRow: " + topRow); } // ... resources、model设置不变 style: TableViewStyle { // ... increment/decrementControl不变 handle: Rectangle { color: "transparent" border.color: "transparent" CustomImage { source: resMgr.getResource("qrc:/Images/Slider/Sliderdot.svg") width: parent.width height: width utilBox {t_left: 20; t_right: 20; t_top: 18; t_bottom: 22;} } } // ... scrollBarBackground、frame、alternateBackgroundColor不变 itemDelegate: Item { // ... 位置、高度设置不变 Text { // ... 其他属性不变 visible: tableView.topRow >= 0 ? (styleData.row >= tableView.topRow) : true } } // ... rowDelegate不变 headerDelegate: Rectangle { id: headerComp // ... 尺寸、颜色设置不变 Text { // ... 文本属性不变 } // 移除Component.onCompleted代码 } } }
内容的提问来源于stack exchange,提问作者Constantin Cojocaru
相关产品推荐
相关产品推荐

