[英]How to get my selection box to move properly using PySide2?
我正在研究 Maya GUI,并使用 QRubberBand 创建了一个拖动选择框。 现在,当我按住“Alt”时,我正试图移动它。 问题是当我移动 QRubberBand 时,它会从盒子的原点移动,就像目前这样。
我想做的是让它从盒子的终点移动,就像这种预期的行为
.
这是代码:
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Form(QtWidgets.QWidget):
def __init__(self):
super(Ui_Form, self).__init__()
self.rubberBand = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)
self.setupUi(self)
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
if event.modifiers() == QtCore.Qt.ShiftModifier:
print 'shift is selected'
elif event.modifiers() == QtCore.Qt.CTRL:
print 'Ctrl is selected'
else:
print 'Reseting selection'
self.origin = event.pos()
self.drag_selection = QtCore.QRect(self.origin, QtCore.QSize())
self.rubberBand.setGeometry(self.drag_selection)
self.rubberBand.show()
def mouseMoveEvent(self, event):
if event.modifiers() == QtCore.Qt.AltModifier:
self.rubberBand.move(event.pos())
self.origin = self.rubberBand.pos()
else:
self.drag_selection = QtCore.QRect(self.origin, event.pos()).normalized()
self.rubberBand.setGeometry(self.drag_selection)
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.rubberBand.hide()
if event.modifiers() == QtCore.Qt.CTRL:
print 'Removing from selection'
else:
print 'Selecting'
它比看起来更棘手,因为您不能简单地将橡皮筋的 position 设置为 cursor,因为它会弹出它而不是像预期的那样翻译它。
因此,我选择使用橡皮筋的几何形状,因为无论用户向哪个方向拖动,它都更加一致。这个想法是当用户按下 alt 键时,我们保存鼠标的当前 position 以便我们可以计算一个增量作为鼠标四处移动。 有了这个增量,我们可以移动几何体并设置它而不会出现任何弹出。 用户也可能反复按下和释放 alt 来调整橡皮筋的大小、移动它、调整大小、移动它等等。所以我们必须考虑到这一点,否则它会弹出。
这是一个似乎有效的完整示例。 希望这些评论可以很容易地遵循逻辑:
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Form(QtWidgets.QWidget):
def __init__(self):
super(Ui_Form, self).__init__()
self.rubberBand = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)
# Create variables that will be handling the moving logic.
self.sourceGeo = None
self.altPoint = None
self.delta = None
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.origin = event.pos()
self.drag_selection = QtCore.QRect(self.origin, QtCore.QSize())
self.rubberBand.setGeometry(self.drag_selection)
self.rubberBand.show()
# Must implement this event to detect when alt gets released
def keyReleaseEvent(self, event):
if event.key() == QtCore.Qt.Key_Alt:
if self.delta is not None:
# This is important: Add delta to origin so that it shifts it over.
# This is needed if the user repeatedly pressed alt to move it, otherwise it would pop.
self.origin += self.delta
# Reset the rest of the variables.
self.sourceGeo = None
self.altPoint = None
self.delta = None
def mouseMoveEvent(self, event):
if event.modifiers() == QtCore.Qt.AltModifier:
# Get the point where alt is pressed and the selection's current geometry.
if self.altPoint is None:
self.sourceGeo = self.rubberBand.geometry()
self.altPoint = event.pos()
self.delta = event.pos() - self.altPoint # Calculate difference from the point alt was pressed to where the cursor is now.
newGeo = QtCore.QRect(self.sourceGeo) # Create a copy
newGeo.moveTopLeft(self.sourceGeo.topLeft() + self.delta) # Apply the delta onto the geometry to move it.
self.rubberBand.setGeometry(newGeo) # Move the selection!
else:
self.drag_selection = QtCore.QRect(self.origin, event.pos()).normalized()
self.rubberBand.setGeometry(self.drag_selection)
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.rubberBand.hide()
inst = Ui_Form()
inst.show()
为此,您需要创建一个偏移量!
这是方法(为了做你所期望的):
def mouseMoveEvent(self, event):
if event.modifiers() == QtCore.Qt.AltModifier:
mouse_x = event.pos().x()
mouse_y = event.pos().y()
rubber_band_w = self.rubberBand.size().width()
rubber_band_h = self.rubberBand.size().height()
self.rubberBand.move(QtCore.QPoint(mouse_x - rubber_band_w, mouse_y - rubber_band_h))
else:
self.drag_selection = QtCore.QRect(self.origin, event.pos()).normalized()
self.rubberBand.setGeometry(self.drag_selection)
为了简化理解,我用 mouse_x、mouse_y、rubber_band_w、rubber_band_h 分解了这个过程,但你可以重构它。
编辑:感谢评论,我意识到我误解了这个问题。 实际上,此解决方案仅适用于向右下方拖动(如第二张图片)。 我认为为了实现这一点,您只需比较鼠标 position 和橡皮筋,以便在后果上产生偏移。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.