调整自定义QTableWidget的大小(宽度/高度)

8
我需要一个基于QTabelModelQTableViewQTableWidget,并在表格上方添加一些按钮。请参见以下图片:

enter image description here

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_()
1个回答

10

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

设置标题中指定逻辑索引的部分可以按照给定模式调整大小的约束条件。在调用此函数时,逻辑索引应该存在。

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_()

enter image description here

在上面的代码中,tableview.horizontalHeader().SetSectionResizeMode(QtWidgets.QHeaderView.Stretch)将Stretch模式应用于所有列,其余三个操作符将相应的列设置为ResizeToContents模式。
小部件窗口的调整大小行为由setSizePolicy方法确定。在这种情况下,策略也可以是tableview.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum),允许用户放大或缩小小部件窗口。

感谢您的回答。因此,在这里,“horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)”将“Stretch”模式应用于所有列,而另外三个语句将各自的列设置为“ResizeToContents”模式;对吗? - AlQuemist
我看到的另一个问题是,被拉伸的列(编号2)可以由用户放大(通过放大窗口),但它无法缩回原始大小!这是预期的行为吗?是否可以允许用户在两个方向上调整大小? - AlQuemist
抱歉表述不够明确。请尝试通过拖动窗口右下角来放大小部件。在“拉伸”模式下的部分将会扩展。然而,尝试将角落拖回原始大小是不可能的,也就是说,列宽可以扩展但无法缩小。如果可能的话,该如何修改这种行为呢? - AlQuemist
我在答案的注释中添加了额外的信息。 - AlQuemist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接