【问题标题】:Adjust the size (width/height) of a custom QTableWidget调整自定义 QTableWidget 的大小(宽/高)
【发布时间】:2019-01-24 08:58:24
【问题描述】:

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

应调整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_()

【问题讨论】:

    标签: pyqt resize qt5 qtablewidget


    【解决方案1】:

    void QHeaderView::setSectionResizeMode(int logicalIndex, QHeaderView::ResizeMode 模式)

    设置如何将标头中由logicalIndex指定的部分调整为给定模式所描述的限制。调用此函数时,逻辑索引应该存在。

    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 模式。

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

    【讨论】:

    • 感谢您的回答。所以,在这里,horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)Stretch 模式应用于all 列,而其他3 个语句将各自的列设置为ResizeToContents 模式;对吗?
    • 我看到的另一个问题是拉伸的列(nr.2)可以被用户放大(通过放大窗口),但不能缩短回原来的大小!这是预期的行为吗?是否可以允许用户调整大小以双向工作?
    • 抱歉含糊不清。只需尝试通过拖动右下角来放大小部件窗口。处于Stretch 模式的部分随后将展开。然而,试图将那个角落拖回来以恢复原来的大小,是不可能的。即列宽可以扩大但不能缩小。如果可能,如何修改这种行为?
    • 我将 cmets 中的附加信息附加到答案中。
    猜你喜欢
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    相关资源
    最近更新 更多