web-dev-qa-db-fra.com

PySide - PyQt: Comment définir une largeur de colonne QTableWidget proportionnelle à l'espace disponible?

Je développe une application informatique avec PySide et j'utilise QTableWidget. Supposons que ma table comporte 3 colonnes, mais les données qu’elles contiennent sont très différentes, comme (pour chaque ligne) une phrase longue dans la première colonne, puis des nombres à 3 chiffres dans les deux dernières colonnes. Je voudrais que redimensionne ma table afin d'ajuster sa taille aux données, ou au moins de pouvoir définir la taille des colonnes à 70/15/15% de l'espace disponible.

Quelle est la meilleure façon de procéder ?

J'ai essayé table.horizontalHeader().setResizeMode(QHeaderView.Stretch) après avoir lu cette question mais cela fait 3 colonnes de la même taille.

J'ai aussi essayé table.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) grâce au commentaire de Fabio / mais il ne remplit pas tout l'espace disponible en cas de besoin.

Ni Interactive, Fixed, Stretch, ResizeToContents de la documentation QHeaderView / semblent me donner ce dont j'ai besoin (voir la deuxième modification).

Toute aide serait la bienvenue, même s’il s’agissait de Qt/C++! Merci beaucoup.


EDIT: J'ai trouvé une solution de contournement, mais ce n'est toujours pas ce que je recherche:

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

Ce serait mieux s'il existait une méthode setStretchFirstSection, mais malheureusement, il ne semble pas en avoir.


EDIT 2:

La seule chose qui peut être modifiée dans le tableau est la dernière colonne, l'utilisateur peut y entrer un nombre. Les flèches rouges indiquent ce que j'aimerais avoir.

Voici ce qui se passe avec Stretch Stretch

Voici ce qui se passe avec ResizeToContents ResizeToContents

7
AdrienW

Cela peut être résolu en définissant le mode de redimensionnement pour chaque colonne. La première section doit s’étirer pour occuper l’espace disponible, tandis que les deux dernières redimensionnent à leur contenu:

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)
19
ekhumoro

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)
5
Xavi Martínez

Vous pouvez le faire avec QItemDelegates ou QStyledItemDelegates. Si vous souhaitez redimensionner les contenus et ont un étirement automatique, vous devez choisir la colonne "étirement".

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

Vous pouvez définir le mode de redimensionnement sur ResizeToContents ou, si vous souhaitez que l'utilisateur puisse ajuster la largeur de la colonne selon vos besoins, appelez simplement resizeColumnsToContents après avoir modifié les éléments du tableau.

Vous devrez peut-être aussi modifier un peu les calculs de largeur à cause des marges et des marges entre les colonnes (par exemple, ajoutez un pixel ou deux au calculated_width pour chaque colonne afin de prendre en compte la bordure de la cellule).

2
Brendan Abel

Comme mentionné précédemment, vous pouvez le faire en définissant le mode de redimensionnement de chaque colonne. Cependant, si vous avez beaucoup de colonnes, cela peut représenter beaucoup de code. La façon dont je le fais est de définir le mode de redimensionnement "général" sur "ResizeToContent" et de "Stretch" pour une (ou plusieurs) colonnes!

Voici le 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)
2
koxx