2017-09-02 53 views
1

我建立這應該接收鼠標右鍵拖動上的QGraphicsView一個PyQt的應用程序時,得出一個「套索」(線從拖拽源延伸到鼠標的位置,和然後在鼠標釋放時擦除套索圖形並顯示應用程序下一部分的輸入對話框。Qt的菜單神器調用輸入對話框

出於某種原因,當我用鼠標點擊「確定」輸入對話框,菜單神器出現在其包含的套索的QGraphicsView。菜單工件是一個下拉菜單行,其中顯示「(複選標記)退出」。偶爾它也可能是我的一個自定義QGraphicsObjects的上下文菜單 - 但無論出於何種原因,調用對話框然後單擊「確定」都會導致QGraphicsView出現意外的右鍵單擊事件。

這似乎只發生在方法的返回前的最後一步是QInputDialog - 有通行證或其他一些方法的調用不會導致神器替換它。我會非常感謝任何人提供有關導致此問題的線索。

下面是最少的代碼:

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

作爲一個實驗,嘗試調用基類的方法,在你開始執行,即'超()。mouseReleaseEvent(事件)'。你也可以在基類調用之前嘗試調用'event.ignore()'。這個想法是讓任何默認行爲在做自己的事情之前發生(或明確地忽略它)。 – ekhumoro

+0

當我調用基類方法時,即使事先調用event.ignore(),也不會改變。然而,我並不完全感到驚訝,因爲基類方法沒有產生這些工件,直到我添加了QInputDialog(並且「(* check mark *)Exit」工件不是我以前見過的任何東西。這些意見和圖形對象的行爲 – Grav

+0

你能提供一個最小的,自包含的例子,這樣其他人可以嘗試重現該問題,否則,你只是迫使人們訴諸猜測 – ekhumoro

回答

0

返回有沒有直接回答這個bug的原因,但使用QTimer.singleShot()調用對話框(在組合之前抑制的默認行爲的Qt使用QSignalMapper來輸入參數)是一種功能性解決方法,它將對話框與發生錯誤的方法分開。感謝@Avaris這一次。

0

這是我的一個猜測,但我以前見過這種奇怪的事情。

一些Qt控件對某些類型的事件的默認行爲。我從來沒有使用QGraphicsView,但通常右鍵點擊的默認值是打開一個上下文相關的彈出式菜單(根據我的經驗,通常無用)。這可能會發生在你的情況中,這可以解釋爲什麼你只有在點擊右鍵時纔會看到這一點。

你可以通過調用event.ignore()mouseReleaseEvent.

+0

我希望是這樣,@ Paul_Cornelius!不幸的是,在返回(或方法中的任何其他地方)之前添加event.ignore()並不能解決問題... – Grav