You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt QML中如何让TableView列宽自适应窗口并支持拖拽调整?

QML实现TableView列宽自适应窗口+拖拽调整

针对Qt 6.8.3版本,要实现表格列宽自适应窗口宽度(左右边界与窗口对齐)且支持鼠标拖拽修改列宽,可通过以下方式实现:

核心修改点

  • 用columnWidthProvider动态计算列宽,同时保存用户手动调整的列宽值
  • 监听窗口尺寸变化,触发表格重新布局
  • 保留resizableColumns: true以支持拖拽调整列宽

修改后的完整代码

import QtQuick
import Qt.labs.qmlmodels
import QtQuick.Controls

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("table modle view")

    // 保存用户调整后的列宽,-1表示自动分配
    ListModel {
        id: columnWidthsModel
        ListElement { width: -1 }
        ListElement { width: -1 }
        ListElement { width: -1 }
        ListElement { width: -1 }
    }

    TableModel {
        id: contactsModel

        TableModelColumn { display: "firstName" }
        TableModelColumn { display: "lastName" }
        TableModelColumn { display: "age" }
        TableModelColumn { display: "phoneNumber" }

        rows: [
            {
                firstName: "John",
                lastName: "Doe",
                age: "49",
                phoneNumber: "111-111-1111"
            },
            {
                firstName: "Jane",
                lastName: "Doe",
                age: "48",
                phoneNumber: "222-222-2222"
            },
            {
                firstName: "George",
                lastName: "Doe",
                age: "12",
                phoneNumber: "333-333-3333"
            },
        ]
    }

    Component {
        id: contactsDelegate

        Rectangle {
            id: delegateRect

            required property bool current

            implicitHeight: 50
            color: current ? "pink" : "lightgray"
            border.width: current ? 2 : 0
            TableView.editDelegate: contactsEditDelegate

            Text {
                text: model.display
                padding: 12
                anchors.fill: parent
            }
        }
    }

    ScrollView {
        id: scrollView

        anchors.top: contactsHHeader.bottom
        anchors.bottom: parent.bottom
        anchors.left: contactsVHeader.right
        anchors.right: parent.right

        TableView {
            id: contactsView

            anchors.fill: parent

            columnSpacing: 1
            rowSpacing: 1
            resizableColumns: true
            resizableRows: true

            model: contactsModel
            delegate: contactsDelegate

            selectionModel: ItemSelectionModel {
                model: contactsView.model
            }

            // 动态提供列宽
            columnWidthProvider: function(column) {
                const savedWidth = columnWidthsModel.get(column).width
                if (savedWidth !== -1) {
                    return savedWidth
                }
                // 自动分配:平均分配可用宽度,扣除列间距
                const availableWidth = scrollView.width - (columnSpacing * (contactsModel.columnCount - 1))
                return availableWidth / contactsModel.columnCount
            }

            // 保存用户手动调整的列宽
            onColumnWidthChanged: {
                columnWidthsModel.setProperty(column, "width", width)
            }
        }
    }

    HorizontalHeaderView {
        id: contactsHHeader

        anchors.left: parent.left
        anchors.right: parent.right
        anchors.leftMargin: contactsVHeader.width
        anchors.top: parent.top

        implicitHeight: 50
        syncView: contactsView
        textRole: "display"

        model: ListModel {
            ListElement{display: "First Name"}
            ListElement{display: "Last Name"}
            ListElement{display: "Age"}
            ListElement{display: "Phone Number"}
        }

        delegate: Rectangle
        {
            color: "#168bcd"
            Text {
                anchors.centerIn: parent
                text: model.display
                padding: 12
            }
        }
    }

    VerticalHeaderView{
        id: contactsVHeader

        anchors.left: parent.left
        anchors.top: parent.top
        anchors.topMargin: contactsHHeader.height

        syncView: contactsView
    }

    Component {
        id: contactsEditDelegate

        TextField {
            anchors.fill: parent
            text: model.display

            horizontalAlignment: TextInput.AlignHCenter
            verticalAlignment: TextInput.AlignVCenter

            TableView.onCommit: {
                let index = TableView.view.index(model.row, model.column)
                model.display = text
            }
        }
    }

    // 窗口宽度变化时,强制表格重新布局以更新列宽
    onWidthChanged: {
        contactsView.forceLayout()
    }
}

代码说明

  1. columnWidthsModel:存储用户手动调整后的列宽,初始值-1表示该列需要自动分配宽度
  2. columnWidthProvider:
    • 如果用户调整过某列宽度,直接返回保存的值
    • 未调整过的列,按平均比例分配ScrollView的可用宽度(扣除列间距)
  3. onColumnWidthChanged:监听列宽拖拽事件,将用户调整后的宽度保存到模型中
  4. onWidthChanged:窗口宽度变化时,调用forceLayout()触发表格重新计算列宽,确保表格始终填满窗口

内容的提问来源于stack exchange,提问作者shanw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:07:11