簡體   English   中英

如何使用 PySide2 讓我的選擇框正確移動?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM