Dragging/Moving a QPushButton in PyQt
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Meditation
--
Chapters
00:00 Dragging/Moving A Qpushbutton In Pyqt
00:48 Accepted Answer Score 19
02:09 Answer 2 Score 2
03:11 Thank you
--
Full question
https://stackoverflow.com/questions/1221...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #pyqt #pyqt4
#avk47
ACCEPTED ANSWER
Score 19
Here is an example of a moveable button that still supports the normal click signal properly:
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_()
In the mousePressEvent I record both the initial start position, and a position that will get updated throughout the drag.
In the mouseMoveEvent, I get the proper offset of the widget from where it was clicked to where the actual origin is, so that the move is accurate.
In the mouseReleaseEvent, I check to see if the overall move was greater than at least a tiny amount. If it was, then it was a drag and we ignore the normal event to not produce a "clicked" signal. Otherwise, we allow the normal event handler to produce the click.
ANSWER 2
Score 2
It depends on what you are trying to do. If you are trying to do actual "Drag & Drop", you're going about it wrong. What you are doing is just moving the button around in its X,Y coordinate space within its parent. Its never actually invoking any Drag/Drop events, those are entirely different.
You should read through the drag & drop documentation here:
http://doc.qt.nokia.com/4.7-snapshot/dnd.html
http://qt-project.org/doc/qt-5.0/qdrag.html
Instead of moving the button within the mousePressEvent, you'll need to create a new QDrag object and execute it. You can make it look like your button by taking a snapshot of your button using the QPixmap::grabWidget method and assign it to the QDrag instance using the QDrag::setPixmap method.
Event if all you are trying to do is move the widget around in the parent space, I would recommend using this framework and just accepting the drop event for your the button. Then you don't trigger a bunch of unnecessary redraws.