Я разрабатываю приложение, используя pyqt 4, поэтому, надеюсь, я делаю только ошибку новобранец.PyQt 4/Qt 4 move QGraphicsItem с помощью мыши с помощью специального обработчика событий
Я обнаружил, что не могу переместить QGraphicsItems и QGraphicsItemGroups в сцену, когда я использую собственные обработчики событий для mousePressEvent() и mouseMoveEvent().
Мое приложение позволяет мне рисовать произвольные фигуры, но я нажимаю модификатор ключа 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_())