在PyQt中拖动/移动QPushButton

Rod*_*Day 8 python pyqt pyqt4

我真的很难找到一种方法来做到这一点.假设我在窗口小部件窗口中非常简单地实现一个按钮:

self.button = QPushButton("Drag Me", self)
Run Code Online (Sandbox Code Playgroud)

我可以通过左右移动父控件区域的初始点self.button.move(x,y),我可以从中获取鼠标事件mousePressEvent(self, e)经过e.x()e.y(),使按钮移动到哪里我点击,但我似乎无法把所有这一切汇集成一个拖放框架.

澄清:在阅读了拖放的"真实"含义后,这不是我需要的.我只想用鼠标移动小部件,这与你在冰箱上移动磁铁的方式非常相似.

jdi*_*jdi 15

下面是一个可移动按钮的示例,它仍然可以正常支持正常的点击信号:

from PyQt4 import QtCore, QtGui


class DragButton(QtGui.QPushButton):

    def mousePressEvent(self, event):
        self.__mousePressPos = None
        self.__mouseMovePos = None
        if event.button() == QtCore.Qt.LeftButton:
            self.__mousePressPos = event.globalPos()
            self.__mouseMovePos = event.globalPos()

        super(DragButton, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton:
            # adjust offset from clicked point to origin of widget
            currPos = self.mapToGlobal(self.pos())
            globalPos = event.globalPos()
            diff = globalPos - self.__mouseMovePos
            newPos = self.mapFromGlobal(currPos + diff)
            self.move(newPos)

            self.__mouseMovePos = globalPos

        super(DragButton, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__mousePressPos is not None:
            moved = event.globalPos() - self.__mousePressPos 
            if moved.manhattanLength() > 3:
                event.ignore()
                return

        super(DragButton, self).mouseReleaseEvent(event)

def clicked():
    print "click as normal!"

if __name__ == "__main__":
    app = QtGui.QApplication([])
    w = QtGui.QWidget()
    w.resize(800,600)

    button = DragButton("Drag", w)
    button.clicked.connect(clicked)

    w.show()
    app.exec_()
Run Code Online (Sandbox Code Playgroud)

mousePressEventI中记录初始开始位置和将在整个拖动过程中更新的位置.

mouseMoveEvent,我得到小部件的正确偏移,从它被点击到实际原点的位置,以便移动是准确的.

mouseReleaseEvent,我检查整体移动是否大于至少一个小量.如果是,那就是拖累,我们忽略正常事件,不产生"点击"信号.否则,我们允许普通事件处理程序产生点击.