Seite 1 von 1
Contextmenü erscheint nicht
Verfasst: Freitag 1. Februar 2013, 14:12
von freak2003
Hallo alle zusammen,
ich programmiere zur Zeit mit pyqt ein gui. Ich habe eine QGraphicsScene die QItems enthält. Jetzt soll bei einem Rechtsklick ein Contextmenü erscheinen. Dabei soll es ein Unterschied sein, ob ich auf ein Item klicke, oder in einen leeren Bereich. Jetzt habe ich für das MousePressEvent den Aufruf angelegt. Aber leider passiert gar nix. Kann mir jemand helfen??
Code: Alles auswählen
class graphicsScene(QtGui.QGraphicsScene):
def __init__ (self, parent = None):
super(graphicsScene, self).__init__ (parent)
def contextMenuEvent(self, event):
self.popMenu = QtGui.QMenu()
self.popMenu.addAction(QtGui.QAction('test0', None))
self.popMenu.addAction(QtGui.QAction('test1', None))
self.popMenu.addSeparator()
self.popMenu.addAction(QtGui.QAction('test2', None))
self.popMenu.exec_(event.globalPos())
def mousePressEvent(self, event):
super(graphicsScene, self).mousePressEvent(event)
pos = event.scenePos()
item = self.itemAt(pos)
if event.button() == QtCore.Qt.LeftButton:
#do something
elif event.button() == QtCore.Qt.RightButton:
self.contextMenuEvent(event)
Re: Contextmenü erscheint nicht
Verfasst: Samstag 2. Februar 2013, 14:08
von EmaNymton
Hast du denn mal getestet, ob der event überhaupt an deine graphicsScene gesendet wird, indem du z.B. mal ein print in die überschriebene Methode einfügst?
Ansonsten kann ich mir nämlich sehr gut vorstellen, dass der Event an die Items geht und deine graphicsScene davon überhaupt nichts mitbekommt.
Re: Contextmenü erscheint nicht
Verfasst: Samstag 2. Februar 2013, 15:00
von freak2003
Hallo,
ja hab ich probiert. Er geht schon in die Funktion "contextMenuEvent" rein. Aber dort passiert nix.
Re: Contextmenü erscheint nicht
Verfasst: Samstag 2. Februar 2013, 15:19
von lunar
@freak2003 Wie kommst Du auf ".globalPos()"? Laut
Dokumentation gibt es diese Methode nicht. Versuche stattdessen ".screenPos()".
Zudem ist es iirc nicht nötig, "mousePressEvent()" zu implementieren, um ein Kontextmenü anzuzeigen. Das Framework sollte ".contextMenuEvent()" automatisch auslösen, wenn Kontextmenü angezeigt werden soll. Insbesondere sorgt das Framework dafür, dass dieses Event entsprechend den Konventionen des Systems ausgelöst wird. Der Klick mit der rechten Maustaste ist nicht auf jedem System der entsprechende Auslöser.
Re: Contextmenü erscheint nicht
Verfasst: Samstag 2. Februar 2013, 15:30
von freak2003
Das mit dem MousePressEvent mache ich, weil beim Linksklick Items platziert werden sollen. Mit ".screenPos()" passiert genau so wenig etwas.
Re: Contextmenü erscheint nicht
Verfasst: Samstag 2. Februar 2013, 16:00
von lunar
@freak2003 Wenn wir Dir weiterhelfen sollen, dann werden wir jetzt wohl vollständigen und ausführbaren Quelltext brauchen, damit wir den Fehler reproduzieren können.
Re: Contextmenü erscheint nicht
Verfasst: Samstag 2. Februar 2013, 16:44
von freak2003
Ich hab mal ein kleines Beispiel mit meinem Code erzeugt. Ich hoffe das hilft weiter!!
Code: Alles auswählen
import math, sys
from PyQt4 import QtCore, QtGui
from gui import Ui_MainWindow
#=========================================================================================
class graphicsScene(QtGui.QGraphicsScene):
def __init__ (self, parent = None):
super(graphicsScene, self).__init__ (parent)
self.tmp_item = []
self.gui = ((self.parent()).parent()).parent()
def contextMenuEvent(self, event):
print("contextMenu")
self.popMenu = QtGui.QMenu()
self.popMenu.addAction(QtGui.QAction('test0', None))
self.popMenu.addAction(QtGui.QAction('test1', None))
self.popMenu.addSeparator()
self.popMenu.addAction(QtGui.QAction('test2', None))
self.popMenu.exec_(event.screenPos())
def mousePressEvent(self, event):
'''Definiert was beim klicken mit der Maus passieren soll'''
super(graphicsScene, self).mousePressEvent(event)
pos = event.scenePos()
item = self.itemAt(pos)
if event.button() == QtCore.Qt.LeftButton:
if item is None:
self.gui.max_node = self.gui.max_node + 1
item = Node(self, self.gui.max_node)
position = QtCore.QPointF(event.scenePos())
item.setPos(position.x() , position.y())
self.addItem(item)
elif event.button() == QtCore.Qt.RightButton:
print("right")
self.contextMenuEvent(event)
#=========================================================================================
class MainWindow(Ui_MainWindow):
def generateStructures(self):
'''GraphicScene einrichten'''
scene = graphicsScene(self.graphicsView)
scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
scene.setSceneRect(-365, -285, 730, 570)
self.graphicsView.setScene(scene)
self.graphicsView.setViewportUpdateMode(QtGui.QGraphicsView.BoundingRectViewportUpdate)
self.graphicsView.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
self.graphicsView.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
def scaleView(self, scaleFactor):
'''Ansicht scalieren'''
factor = self.graphicsView.matrix().scale(scaleFactor, scaleFactor).mapRect(QtCore.QRectF(0, 0, 1, 1)).width()
if factor < 0.07 or factor > 100:
return
self.graphicsView.scale(scaleFactor, scaleFactor)
#=========================================================================================
class MyForm(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.ui = MainWindow()
self.ui.setupUi(self)
self.ui.generateStructures()
self.max_node = 1
# Slots für Schaltflächen einrichten
self.connect(self.ui.pushButtonBeenden,
QtCore.SIGNAL("clicked()"), self.onClose)
# Menüeinträge Funktionen zuweisen
self.ui.actionNeu.triggered.connect(self.onNeu)
self.ui.actionOeffnen.triggered.connect(self.onLoad)
self.ui.actionSpeichern.triggered.connect(self.onSave)
self.ui.actionBeenden.triggered.connect(self.onClose)
def onNeu(self):
self.ui.graphicsView.scene().clear()
def onLoad(self):
pass
def onSave(self):
pass
def onClose(self):
'''Hauptfenster beenden'''
self.close()
#=========================================================================================
class Node(QtGui.QGraphicsItem):
'''
Grafische Darstellung eines Knoten des Graphen
'''
Type = QtGui.QGraphicsItem.UserType + 1
def __init__(self, graphWidget, nr = None):
super(Node, self).__init__()
self.value = nr
self.graph = graphWidget
self.newPos = QtCore.QPointF()
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable)
self.setFlag(QtGui.QGraphicsItem.ItemSendsGeometryChanges)
self.setCacheMode(QtGui.QGraphicsItem.DeviceCoordinateCache)
self.setZValue(1)
def type(self):
'''Gibt den item-typ zurück'''
return Node.Type
def advance(self):
if self.newPos == self.pos():
return False
self.setPos(self.newPos)
return True
def boundingRect(self):
adjust = 2.0
return QtCore.QRectF(-10 - adjust, -10 - adjust, 23 + adjust,
23 + adjust)
def paint(self, painter, option, widget):
'''Überschreibt die paint-methode zu zeichnen eines Knoten'''
node_size = 20
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(QtCore.Qt.darkGray)
painter.drawEllipse(int(math.floor(-node_size * 0.35)), int(math.floor(-node_size * 0.35)),
node_size, node_size)
gradient = QtGui.QRadialGradient(-3, -3, node_size / 2)
if option.state & QtGui.QStyle.State_Sunken:
gradient.setCenter(3, 3)
gradient.setFocalPoint(3, 3)
gradient.setColorAt(1, QtGui.QColor(QtCore.Qt.yellow).light(120))
gradient.setColorAt(0, QtGui.QColor(QtCore.Qt.darkYellow).light(120))
else:
gradient.setColorAt(0, QtCore.Qt.yellow)
gradient.setColorAt(1, QtCore.Qt.darkYellow)
painter.setBrush(QtGui.QBrush(gradient))
painter.setPen(QtGui.QPen(QtCore.Qt.black, 0))
painter.drawEllipse(int(math.floor(-node_size * 0.5)), int(math.floor(-node_size * 0.5)),
node_size, node_size)
painter.setFont(QtGui.QFont('DejaVu Sans', int(math.floor(node_size * 0.4))))
if int(self.value) <= 9:
painter.drawText(int(math.floor(-node_size * 0.2)), int(math.floor(node_size * 0.2)), str(self.value))
else:
painter.drawText(int(math.floor(-node_size * 0.3)), int(math.floor(node_size * 0.2)), str(self.value))
def mousePressEvent(self, event):
self.update()
super(Node, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
self.update()
super(Node, self).mouseReleaseEvent(event)
#=========================================================================================
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
gui.py
Code: Alles auswählen
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.setEnabled(True)
MainWindow.resize(977, 663)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Arial"))
MainWindow.setFont(font)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.graphicsView = QtGui.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(20, 20, 741, 591))
self.graphicsView.setAutoFillBackground(False)
self.graphicsView.setObjectName(_fromUtf8("graphicsView"))
self.pushButtonBeenden = QtGui.QPushButton(self.centralwidget)
self.pushButtonBeenden.setGeometry(QtCore.QRect(820, 570, 98, 27))
font = QtGui.QFont()
font.setFamily(_fromUtf8("Arial"))
self.pushButtonBeenden.setFont(font)
self.pushButtonBeenden.setObjectName(_fromUtf8("pushButtonBeenden"))
self.groupBox = QtGui.QGroupBox(self.centralwidget)
self.groupBox.setGeometry(QtCore.QRect(780, 20, 181, 151))
font = QtGui.QFont()
font.setFamily(_fromUtf8("Arial"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 977, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menuDatei = QtGui.QMenu(self.menubar)
self.menuDatei.setObjectName(_fromUtf8("menuDatei"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.actionNeu = QtGui.QAction(MainWindow)
self.actionNeu.setObjectName(_fromUtf8("actionNeu"))
self.actionOeffnen = QtGui.QAction(MainWindow)
self.actionOeffnen.setObjectName(_fromUtf8("actionOeffnen"))
self.actionSpeichern = QtGui.QAction(MainWindow)
self.actionSpeichern.setObjectName(_fromUtf8("actionSpeichern"))
self.actionBeenden = QtGui.QAction(MainWindow)
self.actionBeenden.setObjectName(_fromUtf8("actionBeenden"))
self.menuDatei.addAction(self.actionNeu)
self.menuDatei.addSeparator()
self.menuDatei.addAction(self.actionOeffnen)
self.menuDatei.addAction(self.actionSpeichern)
self.menuDatei.addSeparator()
self.menuDatei.addAction(self.actionBeenden)
self.menubar.addAction(self.menuDatei.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "PyGraphEdit", None))
self.pushButtonBeenden.setToolTip(_translate("MainWindow", "Beendet das Programm", None))
self.pushButtonBeenden.setText(_translate("MainWindow", "Beenden", None))
self.menuDatei.setTitle(_translate("MainWindow", "Datei", None))
self.actionNeu.setText(_translate("MainWindow", "Neu", None))
self.actionOeffnen.setText(_translate("MainWindow", "Öffnen", None))
self.actionSpeichern.setText(_translate("MainWindow", "Speichern", None))
self.actionBeenden.setText(_translate("MainWindow", "Beenden", None))
MainWindow
Re: Contextmenü erscheint nicht
Verfasst: Samstag 2. Februar 2013, 19:26
von bwbg
Mal so ins Blaue gefragt:
Muss Dein QMenu ggf. mit .show() sichtbar gemacht werden?
Grüße ... bwbg
Re: Contextmenü erscheint nicht
Verfasst: Montag 4. Februar 2013, 10:16
von freak2003
@bwbg: Laut Dokumentation soll es mit popup() oder exec_() sichtbar gemacht werden.
Re: Contextmenü erscheint nicht
Verfasst: Dienstag 5. Februar 2013, 09:23
von freak2003
Ich habs doch noch hinbekommen:
Code: Alles auswählen
def contextMenuEvent(self, event):
'''Kontextmenu beim Rechtsklick anzeigen'''
toolbar = QtGui.QToolBar()
self.actionSettings = toolbar.addAction("Einstellungen", self.gui.onSettings)
self.popMenu = QtGui.QMenu()
self.popMenu.addAction(self.actionSettings)
self.popMenu.exec_(event.screenPos())
Aber trotzdem vielen Dank an alle die mit überlegt haben.
Re: Contextmenü erscheint nicht
Verfasst: Dienstag 5. Februar 2013, 09:51
von BlackJack
@freak2003: Innerhalb einer Ereignisbehandlung so viel an das Objekt zu binden erscheint mir komisch.
Edit: Ebenfalls komisch bis falsch ist es in aller Regel wenn man Qt-Typen denen man ein Elternobjekt bei der Erstellung übergeben kann, keines übergibt. Das hat Auswirkungen auf die Speicherverwaltung auf der Qt-Seite. Das könnte vielleicht sogar das Problem sein, das Qt das `QMenu`-Exemplar bereinigt bevor es angezeigt werden soll, weil es zu keinem übergeordneten Qt-Objekt gehört und damit „Freiwild” ist.