PySide - PyQt : How to make set QTableWidget column width as proportion of the available space?

孤者浪人 提交于 2019-11-28 22:24:52

问题


I'm developing a computer application with PySide and I'm using the QTableWidget. Let's say my table has 3 columns, but the data they contain is very different, like (for each row) a long sentence in the first column, then 3-digit numbers in the two last columns. I'd like to have my table resize in order to adjust its size to the data, or at least to be able to set the column sizes as (say) 70/15/15 % of the available space.

What is the best way to do this ?

I've tried table.horizontalHeader().setResizeMode(QHeaderView.Stretch) after reading this question but it makes 3 columns of the same size.

I've also tried table.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) thanks to Fabio's comment but it doesn't fill all the available space as needed.

Neither Interactive, Fixed, Stretch, ResizeToContents from the QHeaderView documentation seem to give me what I need (see second edit).

Any help would be appreciated, even if it is for Qt/C++ ! Thank you very much.


EDIT : I found kind of a workaround but it's still not what I'm looking for :

header = table.horizontalHeader()
header.setResizeMode(QHeaderView.ResizeToContents)
header.setStretchLastSection(True)

It would be better if there existed a setStretchFirstSection method, but unfortunately there does not seem to be one.


EDIT 2 :

The only thing that can be modified in the table is the last column, the user can enter a number in it. Red arrows indicates what I'd like to have.

Here's what happens with Stretch

Here's what happens with ResizeToContents


回答1:


This can be solved by setting the resize-mode for each column. The first section must stretch to take up the available space, whilst the last two sections just resize to their contents:

PyQt4:

header = self.table.horizontalHeader()
header.setResizeMode(0, QtGui.QHeaderView.Stretch)
header.setResizeMode(1, QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(2, QtGui.QHeaderView.ResizeToContents)

PyQt5:

header = self.table.horizontalHeader()       
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)



回答2:


PyQt4

header = self.table.horizontalHeader()
header.setResizeMode(0, QtGui.QHeaderView.Stretch)
header.setResizeMode(1, QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(2, QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(3, QtGui.QHeaderView.Stretch)

PyQt5

header = self.table.horizontalHeader()       
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QtWidgets.QHeaderView.Stretch)



回答3:


You can do this with QItemDelegates or QStyledItemDelegates. If you want to resize to contents and have automatic stretch, you'll need to choose which column is the "stretch" column.

class ResizeDelegate(QStyledItemDelegate):

    def __init__(self, table, stretch_column, *args, **kwargs):
        super(ResizeDelegate, self).__init__(*args, **kwargs)        
        self.table = table
        self.stretch_column = stretch_column

    def sizeHint(self, option, index):
        size = super(ResizeDelegate, self).sizeHint(option, index)
        if index.column() == self.stretch_column:
            total_width = self.table.viewport().size().width()
            calc_width = size.width()
            for i in range(self.table.columnCount()):
                if i != index.column():
                    option_ = QtGui.QStyleOptionViewItem()
                    index_ = self.table.model().index(index.row(), i)
                    self.initStyleOption(option_, index_)
                    size_ = self.sizeHint(option_, index_)
                    calc_width += size_.width()
            if calc_width < total_width:
                size.setWidth(size.width() + total_width - calc_width)
        return size

...

table = QTableWidget()
delegate = ResizeDelegate(table, 0)
table.setItemDelegate(delegate)
... # Add items to table
table.resizeColumnsToContents()

You can set the resize mode to ResizeToContents, or if you want the user to be able to adjust the column width as needed, just call resizeColumnsToContents manually after making changes to the table items.

You also may need to fudge around with the width calculations a bit because of margins and padding between columns (like add a pixel or two to the calculated_width for each column to account for the cell border).




回答4:


As mentioned before, you can do this by setting the resize-mode of each column. However, if you have a lot of columns this can be a lot of code. The way I do it is setting the "general" resize-mode to "ResizeToContent" and than for one (or more) columns to "Stretch"!

Here is the code:

PyQt4:

header = self.table.horizontalHeader()
header.setResizeMode(QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(0, QtGui.QHeaderView.Stretch)

PyQt5:

header = self.table.horizontalHeader()
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)       
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)


来源:https://stackoverflow.com/questions/38098763/pyside-pyqt-how-to-make-set-qtablewidget-column-width-as-proportion-of-the-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!