我真的很难找到一种方法来做到这一点。假设我在窗口小部件窗口中非常简单地实现了一个按钮:
self.button = QPushButton("Drag Me", self)
我可以使用self.button.move(x,y)
在父窗口小部件区域周围移动其初始化点,我可以通过mousePressEvent(self, e)
和e.x()
从e.y()
获取鼠标事件,以便按钮移动到我点击的任何地方,但我似乎无法将所有这些放在拖放框架中。
答案 0 :(得分:13)
这是一个可移动按钮的示例,它仍然正确支持正常的点击信号:
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
中,我检查整体移动是否大于至少一小部分。如果是,那就是拖累,我们忽略正常事件,不产生“点击”信号。否则,我们允许普通事件处理程序产生单击。
答案 1 :(得分:2)
这取决于你想要做什么。如果你正在尝试实际的“拖放”,那你就错了。你正在做的只是在其父级的X,Y坐标空间中移动按钮。它实际上从未调用任何拖放事件,这些事件完全不同。
你应该通读拖拽和放大器。删除文档:
http://doc.qt.nokia.com/4.7-snapshot/dnd.html
http://qt-project.org/doc/qt-5.0/qdrag.html
您需要创建一个新的QDrag对象并执行它,而不是在mousePressEvent中移动按钮。您可以使用QPixmap :: grabWidget方法拍摄按钮的快照,并使用QDrag :: setPixmap方法将其分配给QDrag实例,使其看起来像您的按钮。
如果你想要做的就是在父空间中移动小部件,我会建议使用这个框架并只接受按钮的放置事件。然后你不会触发一堆不必要的重绘。