调整自定义 QTableWidget 的大小 (width/height)

Adjust the size (width/height) of a custom QTableWidget

我需要一个基于 QTabelModelQTableViewQTableWidget,并在 table 上方添加一些按钮。见下图:

应调整 QTableWidget 的宽度,使其不小于合理的最小值,并且不超出其上方的按钮;特别是,第 1、2 和 4 列的大小应根据其内容进行调整,第 3 列 Aberrations 应扩展以填充右侧的空白.我想知道如何在代码中执行此操作。

以下是我用于自定义 QTableWidget(PyQt5,Python3)的代码的最小示例:

from PyQt5 import QtGui, QtCore, QtWidgets
import numpy as np

#-- Table Model
class MyTableModel(QtCore.QAbstractTableModel):

    def __init__(self, data, parent=None, *args):
        super(MyTableModel, self).__init__(parent)

        # table data
        self.table_data = data
        self.rows_nr, self.columns_nr = data.shape

        # vertical & horizontal header labels
        self.hheaders = ["Head-{}".format(i) for i in range(self.columns_nr)]
        self.vheaders = ["Row-{}".format(i) for i in range(self.rows_nr)]

    # nr of rows
    def rowCount(self, parent):
        return self.rows_nr

    # nr of columns
    def columnCount(self, parent):
        return self.columns_nr

    # row and column headers
    def headerData(self, section, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.hheaders[section]
            #END if

        #ELSE:
        return QtCore.QVariant()

    # display table contents
    def data(self, index, role=QtCore.Qt.DisplayRole):        
        r_ = index.row()
        c_ = index.column()

        if role == QtCore.Qt.DisplayRole:
            return "{}".format(data[r_, c_])
        #ELSE:
        return QtCore.QVariant()

    # set data
    def setData(self, index, value, role):

        r_ = index.row()
        c_ = index.column()

        # editable fields
        if role == QtCore.Qt.EditRole:
            # interprete values
            self.table_data[r_,c_] = str(value)

        return True

    # view/edit flags
    def flags(self, index):
        r_ = index.row()
        c_ = index.column()

        return QtCore.Qt.ItemIsEnabled


class MyTableWidget(QtWidgets.QWidget):
    def __init__(self, data, *args):
        super(MyTableWidget, self).__init__(*args)

        #-- table model
        tablemodel = MyTableModel(data=data, parent=self)

        #-- table view
        tableview = QtWidgets.QTableView()
        tableview.setModel(tablemodel)
        tableview.verticalHeader().hide() # hide vertical/row headers

        # size policy
        tableview.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
        tableview.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)

        #-- layouts
        #--- buttons
        button_hlayout = QtWidgets.QHBoxLayout()
        button_hlayout.addWidget(QtWidgets.QPushButton("Button 1"))
        button_hlayout.addWidget(QtWidgets.QPushButton("Button 2"))
        button_hlayout.addWidget(QtWidgets.QPushButton("Button 3"))

        #--- table
        table_layout = QtWidgets.QVBoxLayout()
        table_layout.addLayout(button_hlayout)
        table_layout.addWidget(tableview)
        self.setLayout(table_layout)
#----------------------------------------

#-- produce sample data
data = np.empty(shape=(3,4), dtype=np.object)
for r in range(3):
    for c in range(4):
        data[r,c] = str(list(range((r+1) * (c+1))))

app = QtWidgets.QApplication([""])
w = MyTableWidget(data=data)
w.show()
app.exec_()

void QHeaderView::setSectionResizeMode(int logicalIndex, QHeaderView::ResizeMode mode)

Sets the constraints on how the section specified by logicalIndex in the header can be resized to those described by the given mode. The logical index should exist at the time this function is called.

from PyQt5 import QtGui, QtCore, QtWidgets
import numpy as np

#-- Table Model
class MyTableModel(QtCore.QAbstractTableModel):

    def __init__(self, data, parent=None, *args):
        super(MyTableModel, self).__init__(parent)

        # table data
        self.table_data = data
        self.rows_nr, self.columns_nr = data.shape

        # vertical & horizontal header labels
        self.hheaders = ["Head-{}".format(i) for i in range(self.columns_nr)]
        self.vheaders = ["Row-{}".format(i) for i in range(self.rows_nr)]

    # nr of rows
    def rowCount(self, parent):
        return self.rows_nr

    # nr of columns
    def columnCount(self, parent):
        return self.columns_nr

    # row and column headers
    def headerData(self, section, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.hheaders[section]
            #END if

        #ELSE:
        return QtCore.QVariant()

    # display table contents
    def data(self, index, role=QtCore.Qt.DisplayRole):        
        r_ = index.row()
        c_ = index.column()

        if role == QtCore.Qt.DisplayRole:
            return "{}".format(data[r_, c_])
        #ELSE:
        return QtCore.QVariant()

    # set data
    def setData(self, index, value, role):

        r_ = index.row()
        c_ = index.column()

        # editable fields
        if role == QtCore.Qt.EditRole:
            # interprete values
            self.table_data[r_,c_] = str(value)

        return True

    # view/edit flags
    def flags(self, index):
        r_ = index.row()
        c_ = index.column()

        return QtCore.Qt.ItemIsEnabled


class MyTableWidget(QtWidgets.QWidget):
    def __init__(self, data, *args):
        super(MyTableWidget, self).__init__(*args)

        #-- table model
        tablemodel = MyTableModel(data=data, parent=self)

        #-- table view
        tableview = QtWidgets.QTableView()
        tableview.setModel(tablemodel)
        tableview.verticalHeader().hide() # hide vertical/row headers
        
        #-- +++
        tableview.setAlternatingRowColors(True)
        tableview.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        tableview.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
        tableview.horizontalHeader().setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
        tableview.horizontalHeader().setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)

        # size policy
        tableview.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
        #tableview.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) # ---
        tableview.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)# +++

        #-- layouts
        #--- buttons
        button_hlayout = QtWidgets.QHBoxLayout()
        button_hlayout.addWidget(QtWidgets.QPushButton("Button 1"))
        button_hlayout.addWidget(QtWidgets.QPushButton("Button 2"))
        button_hlayout.addWidget(QtWidgets.QPushButton("Button 3"))

        #--- table
        table_layout = QtWidgets.QVBoxLayout()
        table_layout.addLayout(button_hlayout)
        table_layout.addWidget(tableview)
        self.setLayout(table_layout)
#----------------------------------------

#-- produce sample data
data = np.empty(shape=(3,4), dtype=np.object)
for r in range(3):
    for c in range(4):
        data[r,c] = str(list(range((r+1) * (c+1))))

app = QtWidgets.QApplication([""])
w = MyTableWidget(data=data)
w.show()
app.exec_()

在上面的代码中,tableview.horizontalHeader().SetSectionResizeMode(QtWidgets.QHeaderView.Stretch)对所有列应用了Stretch模式,其余3个算子将相应的列设置为ResizeToContents模式。

小部件 window 的大小调整行为由 setSizePolicy 方法确定。在这种情况下,策略也可以是tableview.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum),允许用户放大或缩小小部件window。