Qt Quick中TableView不可见问题及布局实现需求
问题解决:QML布局中TableView无法显示并拉伸至底部
问题场景
需要搭建的界面结构:
- 顶部并排显示TextField和Button
- HorizontalHeaderView占满窗口宽度
- TableView占满窗口宽度并延伸至窗口底部
当前问题:TextField和Button正常显示,HorizontalHeaderView仅部分可见,TableView完全不可见,调整height、Layout.preferredHeight等属性无效。
解决方案
问题核心在于布局未正确设置填充规则,以下是修改后的QML代码,关键修改点已标注:
import QtQuick 6.0 import QtQuick.Controls.Basic 6.0 import QtQuick.Layouts 6.0 ApplicationWindow { title: "Portmod" width: 640 height: 480 visible: true header: TabBar { id: mainTabBar width: parent.width TabButton { text: "Manage" width: implicitWidth } TabButton { text: "Search" width: implicitWidth } } StackLayout { id: mainStackLayout currentIndex: mainTabBar.currentIndex anchors.fill: parent // 关键:让StackLayout填满窗口内容区域 ColumnLayout { id: manageTab Layout.fillWidth: true // 关键:让ColumnLayout填充StackLayout的宽度 Layout.fillHeight: true // 关键:让ColumnLayout填充StackLayout的高度 RowLayout { Layout.fillWidth: true // 关键:让RowLayout占满宽度 TextField { placeholderText: "Filter packages..." Layout.fillWidth: true // 关键:让TextField拉伸填满剩余空间 } Button { text: "Filter" } } HorizontalHeaderView { id: installedPackagesHeader syncView: installedPackagesTable Layout.fillWidth: true // 关键:让表头占满窗口宽度 } TableView { id: installedPackagesTable columnSpacing: 1 rowSpacing: 1 clip: true Layout.fillWidth: true // 关键:让TableView占满宽度 Layout.fillHeight: true // 关键:让TableView拉伸至窗口底部 model: installedPackagesModel Keys.onUpPressed: installedPackagesTableVerticalScrollBar.decrease() Keys.onDownPressed: installedPackagesTableVerticalScrollBar.increase() Keys.onLeftPressed: installedPackagesTableHorizontalScrollBar.decrease() Keys.onRightPressed: installedPackagesTableHorizontalScrollBar.increase() ScrollBar.vertical: ScrollBar { id: installedPackagesTableVerticalScrollBar parent: installedPackagesTable } ScrollBar.horizontal: ScrollBar { id: installedPackagesTableHorizontalScrollBar parent: installedPackagesTable } delegate: Rectangle { implicitWidth: 300 implicitHeight: 25 Text { text: display anchors.left: parent.left } } } } Rectangle { id: searchTab anchors.fill: parent // 让搜索页填满窗口 } } }
修改说明
- StackLayout:添加
anchors.fill: parent,确保它填满ApplicationWindow除顶部TabBar外的所有区域。 - ColumnLayout:设置
Layout.fillWidth: true和Layout.fillHeight: true,让它完全填充StackLayout的空间,子元素才能合理分配高度。 - RowLayout:设置
Layout.fillWidth: true,让顶部的搜索栏占满窗口宽度;TextField添加Layout.fillWidth: true,自动拉伸填满按钮外的剩余空间。 - HorizontalHeaderView:添加
Layout.fillWidth: true,保证表头与窗口宽度一致。 - TableView:同时设置
Layout.fillWidth: true和Layout.fillHeight: true,让它填充ColumnLayout的剩余空间,自然延伸至窗口底部。
模型代码(无需修改)
from PySide6.QtCore import QSortFilterProxyModel, QAbstractItemModel, QModelIndex, Qt class InstalledPackagesProxyModel(QSortFilterProxyModel): def __init__(self, data: list[list]) -> None: super().__init__() self.realModel = InstalledPackagesModel(data) self.setSourceModel(self.realModel) def get_atom(self, index: QModelIndex) -> Atom: """ Returns a reference to the source index instead of proxy index, to handle the sorted view. """ mapped_index = self.mapToSource(index) data = [tuple(pkg_data_list) for pkg_data_list in self.realModel._data] return Atom(f"{data[mapped_index.row()][2]}/{data[mapped_index.row()][0]}") class InstalledPackagesModel(QAbstractTableModel): def __init__(self, data: list[list]): super(InstalledPackagesModel, self).__init__() self._data = data self.header_labels = ["Name", "Use Flags", "Category", "Version"] def data(self, index, role): if role == Qt.DisplayRole: # type: ignore value = self._data[index.row()][index.column()] if isinstance(value, Atom): return str(value) return value def rowCount(self, index): return len(self._data) def columnCount(self, index): try: return len(self._data[0]) # If there are no installed mods in the prefix except IndexError: return 1 def headerData(self, section, orientation, role=Qt.DisplayRole): # type: ignore if role == Qt.DisplayRole and orientation == Qt.Horizontal: # type: ignore return self.header_labels[section] return QAbstractTableModel.headerData(self, section, orientation, role)
内容的提问来源于stack exchange,提问作者PopeRigby
相关产品推荐
相关产品推荐

