中的默認mouseEvent功能QGraphicsScene允許通過按住、移動和釋放來移動專案。我正在嘗試用press-and-release-once (pick item)、move (without hold press)、press-and-release-twice (drop item)QGraphicsScene mouseEvent()覆寫該函式以完成相同的移動。我雖然它會很簡單:
self.moving = False
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
if self.moving == False: # first click, pick up, start moving
super().mousePressEvent(event)
self.moving = True
else: # second click, drop, end moving item
super().mouseReleaseEvent(event)
self.moving = False
def mouseMoveEvent(self, event):
if self.moving == True:
super().mousePressEvent(event)
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
pass
到目前為止我無法拿起和移動物品,有人發現有什么問題嗎?另外,我在哪里可以找到的原始實作QGraphicsScene mouseEvent function?
謝謝!
uj5u.com熱心網友回復:
首先,您永遠不能使用錯誤的引數型別呼叫事件處理程式的基本實作。
使用滑鼠移動事件作為其引數呼叫mousePressEvent在概念上是錯誤的,雖然在圖形項上執行它通常不是“危險的”,但在小部件上執行它通常會導致致命的崩潰。
也就是說,如果您想在滑鼠按下和釋放時跟隨滑鼠,這顯然意味著您必須更改mouseReleaseEvent()處理程式中的“跟隨狀態”,而不是那個mousePressEvent()。
此外,您必須確保:
- 釋放滑鼠按鈕后,該專案成為滑鼠抓取器;;
- 該專案還接受懸停事件,因此任何懸停事件(最重要的是懸停移動事件)始終由專案接收和處理;
關于第一點,一般來說,一個小部件(或圖形項)在按下任何滑鼠按鈕時都會成為滑鼠抓取器,直到該按鈕被釋放。成為滑鼠抓取器意味著所有滑鼠事件都被分派到該專案,直到它釋放滑鼠;由于您希望在釋放滑鼠按鈕后能夠接收滑鼠事件,因此您必須在釋放按鈕時顯式抓取(或取消抓取)滑鼠。
在下面的示例中,我將展示如何實作上述內容,并為已經可移動的專案提供支持(通過ItemIsMovable標志)。顯示“可移動標志”文本的專案也可以在按住左鍵的同時移動,否則僅為其他專案提供按下/釋放支持。
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class NoMouseButtonMoveRectItem(QGraphicsRectItem):
moving = False
def mousePressEvent(self, event):
super().mousePressEvent(event)
if event.button() == Qt.LeftButton:
# by defaults, mouse press events are not accepted/handled,
# meaning that no further mouseMoveEvent or mouseReleaseEvent
# will *ever* be received by this item; with the following,
# those events will be properly dispatched
event.accept()
self.pressPos = event.screenPos()
def mouseMoveEvent(self, event):
if self.moving:
self.setPos(self.pos() (event.pos() - self.startPos))
else:
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
if (event.button() != Qt.LeftButton
or event.pos() not in self.boundingRect()):
return
# the following code block is to allow compatibility with the
# ItemIsMovable flag: if the item has the flag set and was moved while
# keeping the left mouse button pressed, we proceed with our
# no-mouse-button-moved approach only *if* the difference between the
# pressed and released mouse positions is smaller than the application
# default value for drag movements; in this way, small, involuntary
# movements usually created between pressing and releasing the mouse
# button will still be considered as candidates for our implementation;
# if you are *not* interested in this flag, just ignore this code block
distance = (event.screenPos() - self.pressPos).manhattanLength()
if (not self.moving and distance > QApplication.startDragDistance()):
return
# end of ItemIsMovable support
self.moving = not self.moving
# the following is *mandatory*
self.setAcceptHoverEvents(self.moving)
if self.moving:
self.startPos = event.pos()
self.grabMouse()
else:
self.ungrabMouse()
if __name__ == '__main__':
import sys
from random import randrange, choice
app = QApplication(sys.argv)
scene = QGraphicsScene()
view = QGraphicsView(scene)
view.resize(QApplication.primaryScreen().size() * 2 / 3)
# create random items that support click/release motion
for i in range(10):
item = NoMouseButtonMoveRectItem(0, 0, 100, 100)
item.setPos(randrange(500), randrange(500))
item.setPen(QColor(*(randrange(255) for _ in range(3))))
if choice((0, 1)):
item.setFlags(item.ItemIsMovable)
QGraphicsSimpleTextItem('Movable flag', item)
else:
item.setBrush(QColor(*(randrange(255) for _ in range(3))))
scene.addItem(item)
view.show()
sys.exit(app.exec_())
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/487703.html
