2017-09-02 47 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