Перетаскивание / перемещение кнопки QPushButton в PyQt

Я действительно изо всех сил пытаюсь понять, как это сделать. Скажем, я реализую кнопку очень просто в окне виджета:

self.button = QPushButton("Drag Me", self)

Я могу переместить его точку инициализации вокруг области родительского виджета, используя self.button.move(x,y), и я могу получить события мыши из mousePressEvent(self, e) via e.x() и e.y(), так что кнопка перемещается туда, куда я нажимаю, но я просто не могу собрать все это вместе в рамки перетаскивания.

уточнение: после чтения на "истинном" значении перетаскивания, это не то, что мне нужно. Я просто хочу иметь возможность перемещать виджет с помощью мыши, очень похоже на то, как вы перемещаете магниты на холодильнике.

2 ответов


вот пример подвижной кнопки, которая по-прежнему поддерживает нормальный сигнал щелчка правильно:

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_()

на mousePressEvent Я записываю как начальную начальную позицию, так и позицию, которая будет обновляться во время перетаскивания.

на mouseMoveEvent, Я получаю правильное смещение виджета от того, где он был нажат, до того, где фактическое происхождение, так что перемещение является точным.

на mouseReleaseEvent, Я проверяю, был ли общий ход больше, чем на совсем немного. Если это было, то это было перетаскивание, и мы игнорируем нормальное событие, чтобы не создавать сигнал "щелкнул". В противном случае мы разрешаем обычному обработчику событий производить щелчок.


Это зависит от того, что вы пытаетесь сделать. Если вы пытаетесь сделать фактическое "перетаскивание", вы идете об этом неправильно. То,что вы делаете, это просто перемещение кнопки в ее координатном пространстве X, Y внутри ее родителя. Его никогда не вызывая каких-либо событий перетаскивания, они совершенно разные.

вы должны прочитать документацию drag & drop здесь:

http://doc.qt.nokia.com/4.7-snapshot/dnd.html
http://qt-project.org/doc/qt-5.0/qdrag.html

вместо перемещения кнопки в mousePressEvent вам нужно создать новый объект QDrag и выполнить его. Вы можете сделать его похожим на вашу кнопку, сделав снимок вашей кнопки с помощью метода QPixmap::grabWidget и назначив его экземпляру QDrag с помощью метода QDrag::setPixmap.

событие, если все вы пытаетесь сделать, это переместить виджет в родительское пространство, я бы рекомендовал использовать эту структуру и просто принять событие drop для вашей кнопки. Тогда вы не запускаете кучу ненужных перерисовок.