QTableView 将小部件缩小到内容

Posted

技术标签:

【中文标题】QTableView 将小部件缩小到内容【英文标题】:QTableView shrink widget to content 【发布时间】:2021-02-17 16:30:48 【问题描述】:

我使用 QTableView 来显示一些数据。到目前为止,这有效。 有一行,当点击这一行时,会出现一些隐藏的行。 单击另一行将隐藏所有其他行。 一排:

多行:

但是我怎样才能去除周围的空白呢? 将strech() 添加到QVBoxLayout 会产生一个半白半灰的窗口,如图所示。 resizeRowsToContents() 也不起作用。添加垫片也没有效果。

我想要的是,Window 保持大小并且空白区域减少到最小(如外部单元格边框)。所以单元格将有一个白色的背景,其余的应该是灰色的。表格视图中是否也有某种“拉伸”? 展开或折叠表格后,周围也应该没有空白。

我的代码,你可以使用:

import sys
import copy
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *


data = [['a','b','c','x','y'],['d','e','f','x','y'],['g','h','i','x','y']]

class TableModel(QAbstractTableModel):
    def __init__(self, data):
        super(TableModel, self).__init__()
        self._data = data

    def data(self, index, role):
        if role == Qt.DisplayRole:
            # See below for the nested-list data structure.
            # .row() indexes into the outer list,
            # .column() indexes into the sub-list
            return self._data[index.row()][index.column()]

    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole:
            row = index.row()
            column = index.column()
            self._data[row][column] = value
            self.dataChanged.emit(index, index)
            return True
        return QAbstractTableModel.setData(self, index, value, role)

    def rowCount(self, index):
        # The length of the outer list.
        return len(self._data)

    def columnCount(self, index):
        # The following takes the first sub-list, and returns
        # the length (only works if all rows are an equal length)
        return len(self._data[0])

class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.selection = data[0]
        # buil UI
        self.init_ui()

    def init_ui(self):
        # layout
        self.box_window = QVBoxLayout()
        # content
        self.invisible_table = QTableView()
        tmp = copy.deepcopy(data)
        tmp.insert(0,self.selection)
        self.model = TableModel(tmp)
        self.invisible_table.setModel(self.model)
        self.invisible_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.invisible_table.horizontalHeader().hide()
        self.invisible_table.horizontalHeader().setMinimumSectionSize(100)
        self.invisible_table.verticalHeader().hide()
        # self.invisible_table.hide()
        for i in range(1,self.model.rowCount(0)):
            self.invisible_table.setRowHidden(i,True)
        self.invisible_table.doubleClicked.connect(self.clicked)
        self.invisible_table.clicked.connect(self.clicked)
        self.invisible_table.setMinimumSize(1,1)
        self.invisible_table.resizeColumnsToContents()
        self.invisible_table.resizeRowsToContents()

        # self.box_window.addLayout(self.visible_line)
        self.box_window.addWidget(self.invisible_table)
        self.box_window.addStretch()
        # build central widget and select it
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.centralWidget().setLayout(self.box_window)

        # show window
        self.setGeometry(50,50,1024,768)
        self.setWindowTitle("Test")
        self.show()

    def popup(self, widget):
        print("popup")
        print(widget)
        self.invisible_table.show()

    def clicked(self, qmi):
        print("clicked")
        rowIndex = qmi.row()
        if rowIndex == 0:
            for i in range(1,self.model.rowCount(0)):
                if self.invisible_table.isRowHidden(i):
                    self.invisible_table.setRowHidden(i,False)
                else:
                    self.invisible_table.setRowHidden(i,True)
        else:
            self.selection = data[rowIndex-1]
            print(self.selection)
            col = 0
            for d in self.selection:
                # self.model._data[0][col]=d
                self.model.setData(self.model.index(0,col),d)
                col += 1
            for i in range(1,self.model.rowCount(0)):
                self.invisible_table.setRowHidden(i,True)

def main():
    app = QApplication(sys.argv)
    main_window = MainWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

[编辑]:根据要求,我想要实现的编辑图像:

[EDIT 2]:这就是它现在的样子。在右侧,应该有这个“下拉列表”(伪组合框) previous approach

【问题讨论】:

你可以展示你想要得到的图像(显然是经过编辑的图像) 【参考方案1】:

我自己解决了这个问题。

解决办法是:

表格最小尺寸必须设置为足够大的值,因此减小窗口不会缩小表格 表格最大尺寸必须设置为最小值,不会裁剪表格

要同时访问两者,可以使用函数setFixedSize()。并且必须通过遍历列和行并总结所有列宽/行高来计算值(宽度和高度)。 唯一要记住的是:当桌子周围有框架时,还必须添加边框线粗细。

每次更改表格布局后都必须设置大小(隐藏/显示行/列,添加/删除行/列,添加/隐藏标题等)

# determine width and height
table_width = 0
table_height = 0
for i in range(table.columnCount()):
    table_width += table.columnWidth(i)
for i in range(table.rowCount()):
    table_height += table.rowHeight(i)
if not table.horizontalHeader().isHidden():
    table_height += table.horizontalHeader().height()
table.verticalHeader().hide()
table.setFrameStyle(QFrame.NoFrame)
table.setFixedSize(table_width,table_height)

结果:

【讨论】:

以上是关于QTableView 将小部件缩小到内容的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 如何将小部件扩展为具有更多内容的更大小部件?

如何在 QTableView 中创建冻结的页脚行

Magento:如何将小部件放入布局 xml?

将小部件名称与小部件一起添加到主屏幕

如何有条件地将小部件添加到列表中?

无法动态地将小部件添加到 QScrollArea 对象