【问题标题】:PyQt 4 / Qt 4 move QGraphicsItem with mouse using custom event handlerPyQt 4 / Qt 4 使用自定义事件处理程序用鼠标移动 QGraphicsItem
【发布时间】:2017-02-28 03:10:43
【问题描述】:

我正在使用 pyqt 4 开发一个应用程序,所以希望我只是犯了一个菜鸟错误。

我发现一旦使用 mousePressEvent() 和 mouseMoveEvent() 的自定义事件处理程序,就无法在场景中移动 QGraphicsItems 和 QGraphicsItemGroups。

我的应用程序允许我绘制任意形状,但是我按 CTRL 键修饰符来设置我的事件处理程序,以便我可以选择对象(并将它们添加到 QGraphicsItemGroup)来移动所有选定的对象。

from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Window(QtGui.QWidget):
def __init__(self):
    QtGui.QWidget.__init__(self)
    self.view = View(self)
    layout = QtGui.QVBoxLayout(self)
    layout.addWidget(self.view)
    self.setMouseTracking(True)
def __init__(self, parent):
    QtGui.QGraphicsView.__init__(self, parent)
    self.activeScene=QtGui.QGraphicsScene(self)
    self.setScene(self.activeScene)
    self.setInteractive(True)
    self.setSceneRect(QtCore.QRectF(self.viewport().rect()))
    self.startpos = None
    self.endpos = None
    self.multiSegmentLine = QtGui.QGraphicsItemGroup(scene=self.activeScene)   
    self.multiSegmentLine.setFlags(QtGui.QGraphicsItemGroup.ItemIsSelectable)
    self.linePen=QPen(Qt.green, 3, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)        
    self.linesegment=QtGui.QGraphicsLineItem

# Create a group of selected items to move as a group        
    self.createMoveGroup = QtGui.QGraphicsItemGroup(scene=self.activeScene)
    self.createMoveGroup.setFlags(QtGui.QGraphicsItemGroup.ItemIsMovable)
    # TESTING
    self.boxxy = self.activeScene.addRect(10,10,100,100,self.linePen)
    self.boxxy.setFlags(QtGui.QGraphicsItem.ItemIsMovable)

# Booleans for state machine 
    self.stateNewLine=True     # Flag to determine line state True = new line, False = continuation of multisegment line
    self.stateSelectItems=False # Flag to help determine True = item selection mode enabled, False = line drawing mode enabled

# Create event handler
def mousePressEvent(self, event):        
    if event.button()==QtCore.Qt.LeftButton:  
        # If CTRL key is not pressed then self.stateSelectItems is FALSE and 
        # mouse handling is normal
        if self.stateSelectItems == False:
            # New line has been started so no end point has been determined
            if self.stateNewLine == True:        
            # Record starting position if creating a new line.  This is used as 
            # origin for line drawn from start position to mouse tip.
                self.startpos = QtCore.QPointF(self.mapToScene(event.pos())) 

            # The line is not new but rather is a multiple segment line.
            elif self.stateNewLine == False:
                # Update the length of the run            
                UserLineList.updateRunLength(self.linesegment.line())
                self.startpos = self.endpos             # Start new line at endpoint of previous segment
                self.segmentCount = self.segmentCount+1     # increment segment count
                #self.multiSegmentLine.setFlag(QtGui.QGraphicsItem.ItemIsMovable)
                # Add line from starting position to location of mouse click   
                #self.linesegment=self.scene().addLine(QtCore.QLineF(self.startpos,self.endpos))  
                self.linesegment = self.activeScene.addLine(QtCore.QLineF(self.startpos,self.endpos))                  
                self.linesegment.setPen(self.linePen)
                # Add newly created line to item group
                self.multiSegmentLine.addToGroup(self.linesegment)
                self.activeScene.addItem(self.multiSegmentLine)
                self.activeScene.removeItem(self.linesegment)

        # If CTRL key is pressed thenself.stateSelectItems == True and mouse 
        # handling has to change to support moving one or more screen items
        elif self.stateSelectItems==True:
            print("ENTERED MOVEMENT MODE!")                
            currentItem=self.activeScene.itemAt(self.mapToScene(event.pos()))               
            if currentItem != None:
                self.createMoveGroup.addToGroup(currentItem)
                self.stateSelectItems = True  # set stateSelectItems flag to control mouse event handling

def mouseDoubleClickEvent(self,event):
#def mouseReleaseEvent(self, event):
    if event.button() == QtCore.Qt.LeftButton:   
        self.startpos=None 
        self.stateNewLine=True # multisegment line has ended
        # Create a record of the multisegment line
        UserLineList.addMultiSegmentLine(self.multiSegmentLine)

def mouseMoveEvent(self,event):  
    # If CTRL key is not pressed then self.stateSelectItems is FALSE and 
    # mouse handling is normal
    if self.stateSelectItems == False:
        # If this is a new line use start position at click
        if self.stateNewLine == True:
            self.endpos = QtCore.QPointF(self.mapToScene(event.pos()))          
            self.linesegment = self.activeScene.addLine(QtCore.QLineF(self.startpos,self.endpos))                        
            self.linesegment.setPen(self.linePen)
            self.stateNewLine = False                                
        # If this line builds upon an existing segment
        elif self.stateNewLine == False:
            self.endpos = QtCore.QPointF(self.mapToScene(event.pos()))          
            self.scene().removeItem(self.linesegment)            
            self.linesegment = self.activeScene.addLine(QtCore.QLineF(self.startpos,self.endpos))            
            self.linesegment.setPen(self.linePen)

    # If CTRL key is pressed thenself.stateSelectItems == True and mouse 
    # handling has to change to support moving one or more screen items        
    elif self.stateSelectItems == True:
        self.createMoveGroup.mouseMoveEvent(self, event)

def keyPressEvent(self,event):
    keyModifier = QtGui.QApplication.keyboardModifiers() #Listen for keyboard modifier keys
    if keyModifier == QtCore.Qt.ControlModifier:
        print("keyEvent Control Key is pressed")
        self.stateSelectItems=True

def keyReleaseEvent(self,event):       
    keyModifier = QtGui.QApplication.keyboardModifiers() #Listen for keyboard modifier keys
    if keyModifier == QtCore.Qt.ControlModifier:
        self.stateSelectItems=False
        self.createMoveGroup.ungrabMouse() # Selected items lose mouse grab
        self.activeScene.destroyItemGroup(self.createMoveGroup) # Remove all selected items from move group

if __name__ == '__main__':
      import sys
      app = QtGui.QApplication(sys.argv)   
      window = Window()
      window.resize(640, 480)
      window.show()
      sys.exit(app.exec_())

【问题讨论】:

    标签: event-handling pyqt mouseevent qgraphicsitem mouse-listeners


    【解决方案1】:

    就像this question 的答案一样,您可能希望调用基类以保持对相应事件的现有事件处理。例如。在鼠标按下事件处理程序中,您将添加如下一行:

    def mousePressEvent(self, event):
        ...
        super(Window, self).mousePressEvent(event)
        ...
    

    对所有自定义事件处理程序以类似的方式执行此操作。

    【讨论】:

      猜你喜欢
      • 2012-01-22
      • 2016-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多