2016-12-22 6 views
4

enter image description hereRedimensionner l'en-tête vertical de QTableView dans PyQt4?

Je dois réduire la taille de la première colonne (la colonne avec les en-têtes verticales)

Comment puis-je redimensionner un en-tête verticale de QTableView en PyQt4?

J'ai de très gros en-têtes et un petit bloc graphique pour montrer cette table, alors aidez-moi!

Je suis capable de redimensionner toutes les colonnes mais je n'arrive pas à comprendre le redimensionnement des en-têtes verticaux?

J'ai essayé beaucoup de choses comme:

self.tableView.setColumnWidth(0, 30) // only able to change the data columns in table not headers 

self.tableView.verticalHeader().setResizeMode(QHeaderView.Interactive) //Able to change the height of headers but not width of them 

Je veux faire les en-têtes qui peuvent être redimensionnées par l'utilisateur et n'a pas de dépendances sur d'autres paramètres du projet, comme la taille de la fenêtre, la taille de autres colonnes ....

Quelqu'un peut-il m'aider avec ceci?

+0

Avez-vous envisagé d'utiliser Qt Designer? – Ronikos

+0

Je suis désolé, je suis nouveau à ce que vous pouvez élaborer? Comment puis-je utiliser Qt Designer? – learncode

+0

Qt Designer vous permet de créer des interfaces utilisateur en utilisant les éléments glisser-déposer. Il est beaucoup plus facile à utiliser que de coder manuellement l'interface utilisateur et il nettoie votre code. Si cela est un grand projet, je recommande vivement envisager de passer à Qt Designer - même si certaines choses doivent encore être codées explicitement, et ironiquement c'est l'un d'entre eux – Ronikos

Répondre

3

Vous pouvez l imitez la taille de l'en-tête vertical en utilisant setMaximWidth et utilisez setTextElideMode pour ajuster la taille du texte.

Cependant, il n'existe pas de méthode intégrée permettant de redimensionner la largeur de l'en-tête verticale par l'utilisateur. Donc, en tant que solution de rechange, vous pouvez utiliser l'événement resize pour ajuster la largeur de l'en-tête vertical à un pourcentage de la largeur totale. De cette façon, le redimensionnement de la fenêtre modifiera également la largeur de l'en-tête vertical.

Voici un script de démonstration qui implémente tout cela:

import sys 
from PyQt4 import QtCore, QtGui 

class Window(QtGui.QWidget): 
    def __init__(self, rows, columns): 
     super(Window, self).__init__() 
     self.table = QtGui.QTableView(self) 
     self.table.installEventFilter(self) 
     self.table.verticalHeader().setTextElideMode(QtCore.Qt.ElideRight) 
     model = QtGui.QStandardItemModel(rows, columns, self.table) 
     for row in range(rows): 
      item = QtGui.QStandardItem('FOO_BAR_123_AB_CD_%s' % row) 
      model.setVerticalHeaderItem(row, item) 
      for column in range(columns): 
       item = QtGui.QStandardItem('(%d, %d)' % (row, column)) 
       item.setTextAlignment(QtCore.Qt.AlignCenter) 
       model.setItem(row, column, item) 
     self.table.setModel(model) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.table) 

    def eventFilter(self, source, event): 
     if event.type() == QtCore.QEvent.Resize and source is self.table: 
      source.verticalHeader().setMaximumWidth(source.width()/4) 
     return super(Window, self).eventFilter(source, event) 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window(15, 5) 
    window.setGeometry(600, 100, 400, 300) 
    window.show() 
    sys.exit(app.exec_()) 

MISE À JOUR:

J'ai eu un aller à écrire une classe d'en-tête personnalisé qui implémente le redimensionnement de l'utilisateur de la largeur d'en-tête verticale. Il fonctionne presque, mais je ne trouve pas un moyen de mettre à jour la vue correctement tout en faisant glisser avec la souris. Quoi qu'il en soit, voici une démo de ce que j'ai jusqu'à présent au cas où quelqu'un peut voir comment faire fonctionner:

import sys 
from PyQt4 import QtCore, QtGui 

class HeaderView(QtGui.QHeaderView): 
    def __init__(self, table): 
     super(HeaderView, self).__init__(QtCore.Qt.Horizontal, table) 
     self.setClickable(True) 
     self.setHighlightSections(True) 
     self.setResizeMode(QtGui.QHeaderView.Interactive) 
     self._vheader = table.verticalHeader() 
     self._resizing = False 
     self._start_position = -1 
     self._start_width = -1 

    def mouseMoveEvent(self, event): 
     if self._resizing: 
      width = event.x() - self._start_position + self._start_width 
      if width > 0: 
       self._vheader.setFixedWidth(width) 
       # TODO: find a proper replacement for this 
       self.geometriesChanged.emit() 
     else: 
      super(HeaderView, self).mouseMoveEvent(event) 
      if 0 <= event.x() <= 3: 
       if not self.testAttribute(QtCore.Qt.WA_SetCursor): 
        self.setCursor(QtCore.Qt.SplitHCursor) 

    def mousePressEvent(self, event): 
     if not self._resizing and event.button() == QtCore.Qt.LeftButton: 
      if 0 <= event.x() <= 3: 
       self._start_position = event.x() 
       self._start_width = self._vheader.width() 
       self._resizing = True 
       return 
     super(HeaderView, self).mousePressEvent(event) 

    def mouseReleaseEvent(self, event): 
     self._resizing = False 
     super(HeaderView, self).mouseReleaseEvent(event) 

class Window(QtGui.QWidget): 
    def __init__(self, rows, columns): 
     super(Window, self).__init__() 
     self.table = QtGui.QTableView(self) 
     self.table.setHorizontalHeader(HeaderView(self.table)) 
     self.table.verticalHeader().setTextElideMode(QtCore.Qt.ElideRight) 
     model = QtGui.QStandardItemModel(rows, columns, self.table) 
     for row in range(rows): 
      item = QtGui.QStandardItem('FOO_BAR_123_AB_CD_%s' % row) 
      item.setToolTip(item.text()) 
      model.setVerticalHeaderItem(row, item) 
      for column in range(columns): 
       item = QtGui.QStandardItem('(%d, %d)' % (row, column)) 
       item.setTextAlignment(QtCore.Qt.AlignCenter) 
       model.setItem(row, column, item) 
     self.table.setModel(model) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.table) 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window(15, 5) 
    window.setGeometry(600, 100, 400, 300) 
    window.show() 
    sys.exit(app.exec_()) 
+0

merci pour la réponse! J'ai pensé à cette alternative d'avoir une maxWidth fixe, mais ce n'est pas exactement ce que je cherchais. Donc vous dites qu'il n'y a aucun moyen qu'un utilisateur puisse redimensionner cet en-tête sur son testament. – learncode

+0

Ceci est un gros problème car certains d'en-tête ont juste un caractère et certains fichiers ont environ 1000 caractères, donc je ne veux pas fixer la taille avec maxWidth, – learncode

+1

@VenkataNarsiReddyVaddula. La largeur maximale n'est pas fixe. Il est ajusté dans l'événement resize lorsque la fenêtre est redimensionnée. J'ai utilisé un pourcentage de la largeur de la table, mais vous pouvez utiliser la méthode que vous voulez pour la définir. – ekhumoro

0

PyQt a tendance à avoir une mauvaise documentation, mais this page donne toutes les informations possibles sur la classe QTableView.

Je ne sais pas ce que votre problème est, mais vous pouvez essayer:

self.tableView.horizontalHeader().setSectionResizeMode(3) 

The documentation of .setSectionResize()

Sinon, si vous voulez redimensionner chaque en-tête à une taille de jeu, essayez:

self.tableView.horizontalHeader().resizeSection(0, pixelSize1) 
self.tableView.horizontalHeader().resizeSection(1, pixelSize2) 
self.tableView.horizontalHeader().resizeSection(2, pixelSize3) 
... 

The documentation of .resizeSection()

+0

j'ai téléchargé une image qui peut vous aider à mieux comprendre le problème. Aussi QHeaderView n'a pas setSectionResizeMode(), j'ai essayé setResizeMode() – learncode

1

solution de Ekhumoro fonctionne presque parfait. Le comportement de déplacement en hachage observé lors du redimensionnement est lié à la modification de l'espace de coordonnées pendant le redimensionnement.

Pour corriger ce comportement saccadé et un redimensionnement en douceur, vous devez utiliser l'espace de coordonnées global plutôt que la coordonnée locale pour le headerView. Pour ce faire, tout simplement remplacer event.x() avec event.globalX()

 #width = event.x() - self._start_position + self._start_width 
     width = event.globalX() - self._start_position + self._start_width 

      #self._start_position = event.x() 
      self._start_position = event.globalX() 

Je change également le signal Changed geometried à emited de l'en-tête verticale et non l'en-tête horizontale. Comme c'était l'en-tête vertical qui changeait réellement de taille. Cependant, dans mon test, je ne pouvais pas dire que cela avait beaucoup d'importance, mais conceptuellement, cela semble correct.

  #self.geometriesChanged.emit() 
      self._vheader.geometriesChanged.emit()