Comment puis-je obtenir les menus contextuels pour les clics dans QTableView en-tête?
L'exemple de code ci-dessous (fortement influencé par ici) dispose d'un droit-cliquez sur le menu contextuel qui apparaît comme l'utilisateur clique sur les cellules du tableau. Est-il possible d'avoir un autre clic droit menu contextuel clique avec le bouton droit dans l'en-tête de la table? Si oui, comment puis-je changer le code à intégrer cette?
import re
import operator
import os
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
self.tabledata = [('apple', 'red', 'small'),
('apple', 'red', 'medium'),
('apple', 'green', 'small'),
('banana', 'yellow', 'large')]
self.header = ['fruit', 'color', 'size']
# create table
self.createTable()
# layout
layout = QVBoxLayout()
layout.addWidget(self.tv)
self.setLayout(layout)
def popup(self, pos):
for i in self.tv.selectionModel().selection().indexes():
print i.row(), i.column()
menu = QMenu()
quitAction = menu.addAction("Quit")
action = menu.exec_(self.mapToGlobal(pos))
if action == quitAction:
qApp.quit()
def createTable(self):
# create the view
self.tv = QTableView()
self.tv.setStyleSheet("gridline-color: rgb(191, 191, 191)")
self.tv.setContextMenuPolicy(Qt.CustomContextMenu)
self.tv.customContextMenuRequested.connect(self.popup)
# set the table model
tm = MyTableModel(self.tabledata, self.header, self)
self.tv.setModel(tm)
# set the minimum size
self.tv.setMinimumSize(400, 300)
# hide grid
self.tv.setShowGrid(True)
# set the font
font = QFont("Calibri (Body)", 12)
self.tv.setFont(font)
# hide vertical header
vh = self.tv.verticalHeader()
vh.setVisible(False)
# set horizontal header properties
hh = self.tv.horizontalHeader()
hh.setStretchLastSection(True)
# set column width to fit contents
self.tv.resizeColumnsToContents()
# set row height
nrows = len(self.tabledata)
for row in xrange(nrows):
self.tv.setRowHeight(row, 18)
# enable sorting
self.tv.setSortingEnabled(True)
return self.tv
class MyTableModel(QAbstractTableModel):
def __init__(self, datain, headerdata, parent=None, *args):
""" datain: a list of lists
headerdata: a list of strings
"""
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain
self.headerdata = headerdata
def rowCount(self, parent):
return len(self.arraydata)
def columnCount(self, parent):
return len(self.arraydata[0])
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self.headerdata[col])
return QVariant()
def sort(self, Ncol, order):
"""Sort table by given column number.
"""
self.emit(SIGNAL("layoutAboutToBeChanged()"))
self.arraydata = sorted(self.arraydata, key=operator.itemgetter(Ncol))
if order == Qt.DescendingOrder:
self.arraydata.reverse()
self.emit(SIGNAL("layoutChanged()"))
if __name__ == "__main__":
main()
OriginalL'auteur c00kiemonster | 2011-10-16
Vous devez vous connecter pour publier un commentaire.
S'est avéré être plus simple que je ne le pensais. De la même manière que j'ai ajouter le menu contextuel pour le QTableView widget lui-même, je peux juste l'en-tête du tableau d'objet et puis attacher un menu contextuel de la même manière que je l'ai fait avec l'ordinaire menu contextuel.
OriginalL'auteur c00kiemonster
Il y a un autre moyen plus puissant pour ce faire, si vous prenez le étape et d'hériter de la vue au lieu de simplement la composition. N'menu contextuel personnalisé travailler ici? Oui, mais pourquoi n'est rien d'autre que le point de vue devez savoir à ce sujet? Il sera également l'aider à mieux la forme de votre code de traiter avec d'autres questions correctement. Actuellement, la mise en œuvre ne fournit pas toute l'encapsulation, de cohésion ou de soutien de la séparation de la responsabilité. À la fin vous aurez un grand blob qui est l'antithèse de la bonne conception.
Je mentionne cela parce que vous semblez être de placer l'ensemble de l'interface graphique de la Logique dans ce croissant fonction principale, et c'est la raison pour laquelle vous fini par mettre la sorte la mise en œuvre à l'intérieur de votre modèle, ce qui n'a aucun sens pour moi. (Si vous avez deux points de vue du modèle, vous obligeant à être classés de la même façon)
Est-il plus de code? Oui, mais il vous donne plus de puissance, ce qui je pense vaut la peine de mentionner. Ci-dessous, je suis à la démonstration de la façon de gérer les en-têtes et aussi une cellule donnée que vous voulez. Notez également que, dans mon œuvre, si certaines AUTRES widget existe, qui définit aussi un menu contextuel du gestionnaire d'événement il est possible d'obtenir une chance d'avoir de fissure à la gestion de l'événement de l'après mine; en sorte que si quelqu'un ajoute un gestionnaire pour seulement certains cas, ils peuvent le faire, sans pour autant compliquer mon code. Une partie de cela est de marquage si vous avez géré l'événement ou non.
Assez de mes divagations et les pensées voici le code:
pass
commandes dans votre si les déclarations...Je suis bien conscient qu'ils ne sont pas nécessaires et sont un no-op. Pour moi (et les gens, je travaille avec), nous trouvons, il augmente considérablement la lisibilité d'autant que nous hop-et-vient à partir de C/C++, et c'est quelque chose de la PEP-8 avocats. Personnellement, j'ai aussi comme eux ainsi que de style-outils de mise en forme peut indentation des problèmes dans un contexte de libre-manière, la génération de code outils pouvez insérer des talons pour moi avec un fini fin, et il fait fusionne plus facile quand les gens réécrire quelque chose de l'évolution des niveaux d'imbrication.
Ok, merci pour les explications. J'ai pensé que c'était par habitude plutôt que par l'ignorance, et j'étais curieux de savoir pourquoi. Très apprécié.
toujours un plaisir de vous expliquer, mais si vous êtes curieux, vous pouvez toujours demander directement à votre question, c'est un Q&Un site 😛
Je pense que vous ne comprenez pas et je ne vois pourquoi du comment je l'ai écrit. Par directement, je suis seulement en se référant à la façon dont vous "demander" dans votre commentaire. Vous n'avez pas poser une question; vous avez fait une déclaration indirectement questionnement je suis en train de faire. Comparez cela à la question directe "je suis en supposant que vous savez qui passe n'est pas requis; êtes-vous de l'utiliser hors de l'habitude ou pour une autre raison?" Beaucoup plus susceptibles d'être: bien reçu, pour moi, pour la marque de votre commentaire utile et de ne pas faire le destinataire se sentir sur la défensive. ( Je suis d'accord bon pour les autres, comment avez-vous message directement? )
OriginalL'auteur UpAndAdam