2017-09-02 5 views
1

Ich erstelle eine PyQt-Anwendung, die Maus-Rechtsklick-Drags auf eine QGraphicsView erhalten soll, ein "Lasso" zeichnen (eine Linie, die sich vom Drag-Ursprung zur Mausposition erstreckt) Kreis an der Mausposition), und dann, beim Loslassen der Maus, löschen Sie die Lasso-Grafiken und zeigen Sie einen Eingabedialog für den nächsten Teil der App an.Qt-Menüartefakt beim Aufruf des Eingabedialogs

Aus irgendeinem Grund erscheint ein Menüartefakt in der QGraphicsView, das das Lasso enthält, wenn ich im Eingabedialog mit der Maus auf "OK" klicke. Das Menüartefakt ist eine Dropdown-Menüzeile mit der Aufschrift "(Häkchen) Exit". Gelegentlich kann es auch das Kontextmenü für eines meiner benutzerdefinierten QGraphicsObjects sein - aber aus welchem ​​Grund auch immer, das Aufrufen des Dialogs und das Klicken auf "Ok" führt zu einem unbeabsichtigten Rechtsklick-ähnlichen Ereignis in der QGraphicsView.

Dies scheint nur dann zu passieren, wenn der letzte Schritt vor der Methodenrückgabe der QInputDialog ist - das Ersetzen durch einen Durchlauf oder ein Aufruf einer anderen Methode führt nicht zum Artefakt. Ich wäre jedem dankbar, der weiß, was das Problem verursacht!

Hier ist der minimale Code:

import sys 
from PyQt4 import QtCore, QtGui 

class Window(QtGui.QMainWindow): 
    # The app main window. 

    def __init__(self): 
     super(Window, self).__init__() 

     # Initialize window UI 
     self.initUI() 


    def initUI(self, labelText=None): 
     # Set user-interface attributes. 

     # Set up menu-, tool-, status-bars and add associated actions. 
     self.toolbar = self.addToolBar('Exit') 

     # Create a menu item to exit the app. 
     exitAction = QtGui.QAction(QtGui.QIcon('icons/exit.png'), '&Exit', self) 
     exitAction.triggered.connect(QtGui.qApp.quit) 
     self.toolbar.addAction(exitAction) 

     # Create the main view. 
     self.viewNetwork = NetworkPortal() 
     self.viewNetwork.setMinimumWidth(800) 
     self.viewNetwork.setMinimumHeight(800) 

     self.setCentralWidget(self.viewNetwork) 
     self.show() 


class NetworkPortal(QtGui.QGraphicsView): 
    # A view which allows you to see and manipulate a network of nodes. 

    def __init__(self): 
     super(NetworkPortal, self).__init__(QtGui.QGraphicsScene()) 

     # Add the CircleThing graphic to the scene. 
     circleThing = CircleThing() 
     self.scene().addItem(circleThing) 


class CircleThing(QtGui.QGraphicsEllipseItem): 
    # Defines the graphical object. 

    def __init__(self): 
     super(CircleThing, self).__init__(-10, -10, 20, 20) 

     # Set flags for the graphical object. 
     self.setFlags(
         QtGui.QGraphicsItem.ItemIsSelectable | 
         QtGui.QGraphicsItem.ItemIsMovable | 
         QtGui.QGraphicsItem.ItemSendsScenePositionChanges 
        ) 

     self.dragLine = None 
     self.dragCircle = None 

    def mouseMoveEvent(self, event): 
     # Reimplements mouseMoveEvent to drag out a line which can, on 
     # mouseReleaseEvent, form a new Relationship or create a new Thing. 

     # If just beginning a drag, 
     if self.dragLine == None: 

      # Create a new lasso line. 
      self.startPosX = event.scenePos().x() 
      self.startPosY = event.scenePos().y() 
      self.dragLine = self.scene().addLine(
         self.startPosX, 
         self.startPosY, 
         event.scenePos().x(), 
         event.scenePos().y(), 
         QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.SolidLine) 
         ) 

      # Create a new lasso circle at the location of the drag position. 
      self.dragCircle = QtGui.QGraphicsEllipseItem(-5, -5, 10, 10) 
      self.dragCircle.setPos(event.scenePos().x(), 
            event.scenePos().y()) 
      self.scene().addItem(self.dragCircle) 

     # If a drag is already in progress, 
     else: 

      # Move the lasso line and circle to the drag position. 
      self.dragLine.setLine(QtCore.QLineF(self.startPosX, 
               self.startPosY, 
               event.scenePos().x(), 
               event.scenePos().y())) 
      self.dragCircle.setPos(event.scenePos().x(), 
            event.scenePos().y()) 


    def mouseReleaseEvent(self, event): 

     # If the line already exists, 
     if self.dragLine != None: 

      # If the released button was the right mouse button, 
      if event.button() == QtCore.Qt.RightButton: 

       # Clean up the link-drag graphics. 
       self.scene().removeItem(self.dragLine) 
       self.dragLine = None 
       self.scene().removeItem(self.dragCircle) 
       self.dragCircle = None 

       # Create the related Thing. 
       # Display input box querying for name value. 
       entry, ok = QtGui.QInputDialog.getText(None, 'Enter some info: ', 
              'Input:', QtGui.QLineEdit.Normal, '') 

       return 


if __name__ == "__main__": 

    app = QtGui.QApplication(sys.argv) 
    newWindow = Window() 
    sys.exit(app.exec_()) 
+0

Versuchen Sie als Versuch, die Basisklassenmethode zu Beginn Ihrer Implementierung aufzurufen, d. H. 'Super(). MouseReleaseEvent (event)'. Sie könnten auch versuchen, 'event.ignore()' vor dem Aufruf der Basisklasse aufzurufen. Die Idee ist, jedes Standardverhalten passieren zu lassen (oder es explizit zu ignorieren), bevor Sie Ihre eigenen Sachen machen. – ekhumoro

+0

Keine Änderung, wenn ich die Basisklasse-Methode aufrufen, auch mit event.ignore() davor. Ich bin jedoch nicht völlig überrascht, da die Basisklassenmethode diese Artefakte erst erzeugt, nachdem ich den QInputDialog hinzugefügt habe (und auch das Artefakt "(* Häkchen *) Beenden" ist nichts, was ich zuvor in der Verhalten dieser Ansichten und Grafikobjekte – Grav

+0

Können Sie ein minimales, in sich geschlossenes Beispiel angeben, damit andere versuchen können, das Problem zu reproduzieren? Andernfalls zwingen Sie die Leute nur dazu, auf Raten zu setzen. – ekhumoro

Antwort

0

Es gibt nicht eine direkte Antwort auf die Ursache für diesen Fehler war, aber mit einem QTimer.singleShot(), um den Dialog zu nennen (in Kombination mit einem QSignalMapper, um Parameter einzugeben) ist eine funktionale Problemumgehung, die den Dialog von der Methode trennt, in der der Fehler auftrat. Danke an @Avaris für diesen.

0

Dies ist eine Vermutung meinerseits, aber ich habe diese Art seltsame Sache gesehen vor.

Einige Qt-Widgets verhalten sich standardmäßig bei bestimmten Ereignistypen. Ich habe noch nie QGraphicsView benutzt, aber oft ist der Standard für einen Rechtsklick, um ein kontext-sensitives Popup-Menü zu öffnen (in der Regel nutzlos, meiner Erfahrung nach). Das könnte in Ihrem Fall passieren, was erklären würde, warum Sie das nur sehen, wenn Sie mit der rechten Maustaste klicken.

Sie können den Standard Qt Verhalten unterdrücken, indem event.ignore() Aufruf vor der Rückkehr mouseReleaseEvent.

+0

Ich wünschte, das wäre der Fall, @ Paul_Cornelius! Das Hinzufügen eines event.ignore() vor der Rückgabe (oder anderswo in der Methode) behebt das Problem leider nicht ... – Grav

Verwandte Themen