Python PyQt4-拖放
嘿,为了理解PyQt4中的拖放方法,我一直在学习这个。然而,我无法理解以下几点。如果有人能对我说得更清楚就好了Python PyQt4-拖放,python,qt,button,drag-and-drop,pyqt4,Python,Qt,Button,Drag And Drop,Pyqt4,嘿,为了理解PyQt4中的拖放方法,我一直在学习这个。然而,我无法理解以下几点。如果有人能对我说得更清楚就好了 def mouseMoveEvent(self, e): //class Button mimeData = QtCore.QMimeData() drag = QtGui.QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(e.pos() - self.rect().topLeft())
def mouseMoveEvent(self, e): //class Button
mimeData = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
dropAction = drag.start(QtCore.Qt.MoveAction)
def dropEvent(self, e): //class Example
position = e.pos()
self.button.move(position)
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
为什么有一个单独的self.button.move()和e.setDropAction()不self.button.move()实际上是移动按钮本身?有人能解释一下drag.setHotSpot和drag.start()的作用吗?谢谢。那个教程已经严重过时了<代码>QDrag.start已从过时。应该改用 从
exec
的文档中可以看到,它有一个返回值<dropEvent
中的code>setDropAction确定此值。它不执行移动。这就是为什么需要一个self.button.move()
来进行实际移动。那么,setDropAction
有什么意义呢?你可能需要知道你做了什么样的拖动操作。假设您正在两个列表小部件之间实现拖放。如果您执行了移动操作,这意味着您需要从源窗口小部件中删除该项,并在目标窗口小部件中创建一个。如果是复制操作,则可以保留原始文件,只需在目标中创建副本
sethospot
/hospot
与QDrag的setPixmap
相关。拖动项目时,可以显示QPixmap
<代码>热点
确定pixmap的位置。将定位pixmap,使光标位于相对于pixmap左上角的热点处。因此,在该教程中,它是毫无意义的,因为没有要显示的pixmap
这里是该教程的一个稍加修改和更新的版本。希望我的评论足够多。您可以使用右键单击移动
或使用Shift+右键单击复制
:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
class Button(QtGui.QPushButton):
def mouseMoveEvent(self, e):
if e.buttons() != QtCore.Qt.RightButton:
return
# write the relative cursor position to mime data
mimeData = QtCore.QMimeData()
# simple string with 'x,y'
mimeData.setText('%d,%d' % (e.x(), e.y()))
# let's make it fancy. we'll show a "ghost" of the button as we drag
# grab the button to a pixmap
pixmap = QtGui.QPixmap.grabWidget(self)
# below makes the pixmap half transparent
painter = QtGui.QPainter(pixmap)
painter.setCompositionMode(painter.CompositionMode_DestinationIn)
painter.fillRect(pixmap.rect(), QtGui.QColor(0, 0, 0, 127))
painter.end()
# make a QDrag
drag = QtGui.QDrag(self)
# put our MimeData
drag.setMimeData(mimeData)
# set its Pixmap
drag.setPixmap(pixmap)
# shift the Pixmap so that it coincides with the cursor position
drag.setHotSpot(e.pos())
# start the drag operation
# exec_ will return the accepted action from dropEvent
if drag.exec_(QtCore.Qt.CopyAction | QtCore.Qt.MoveAction) == QtCore.Qt.MoveAction:
print 'moved'
else:
print 'copied'
def mousePressEvent(self, e):
QtGui.QPushButton.mousePressEvent(self, e)
if e.button() == QtCore.Qt.LeftButton:
print 'press'
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setAcceptDrops(True)
button = Button('Button', self)
button.move(100, 65)
self.buttons = [button]
self.setWindowTitle('Copy or Move')
self.setGeometry(300, 300, 280, 150)
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
# get the relative position from the mime data
mime = e.mimeData().text()
x, y = map(int, mime.split(','))
if e.keyboardModifiers() & QtCore.Qt.ShiftModifier:
# copy
# so create a new button
button = Button('Button', self)
# move it to the position adjusted with the cursor position at drag
button.move(e.pos()-QtCore.QPoint(x, y))
# show it
button.show()
# store it
self.buttons.append(button)
# set the drop action as Copy
e.setDropAction(QtCore.Qt.CopyAction)
else:
# move
# so move the dragged button (i.e. event.source())
e.source().move(e.pos()-QtCore.QPoint(x, y))
# set the drop action as Move
e.setDropAction(QtCore.Qt.MoveAction)
# tell the QDrag we accepted it
e.accept()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
Avaris的答案适用于PyQt5和Python 3
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Adapted for PyQt5 and Python 3 from Avaris' answer to
# https://stackoverflow.com/questions/14395799/pyqt4-drag-and-drop
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QApplication
from PyQt5.QtCore import Qt, QMimeData, QPoint
from PyQt5.QtGui import QDrag, QPixmap, QPainter, QColor
class Button(QPushButton):
def mouseMoveEvent(self, e):
if e.buttons() != Qt.RightButton:
return
# write the relative cursor position to mime data
mimeData = QMimeData()
# simple string with 'x,y'
mimeData.setText('%d,%d' % (e.x(), e.y()))
# let's make it fancy. we'll show a "ghost" of the button as we drag
# grab the button to a pixmap
pixmap = QWidget.grab(self)
# below makes the pixmap half transparent
painter = QPainter(pixmap)
painter.setCompositionMode(painter.CompositionMode_DestinationIn)
painter.fillRect(pixmap.rect(), QColor(0, 0, 0, 127))
painter.end()
# make a QDrag
drag = QDrag(self)
# put our MimeData
drag.setMimeData(mimeData)
# set its Pixmap
drag.setPixmap(pixmap)
# shift the Pixmap so that it coincides with the cursor position
drag.setHotSpot(e.pos())
# start the drag operation
# exec_ will return the accepted action from dropEvent
if drag.exec_(Qt.CopyAction | Qt.MoveAction) == Qt.MoveAction:
print('moved')
else:
print('copied')
def mousePressEvent(self, e):
QPushButton.mousePressEvent(self, e)
if e.button() == Qt.LeftButton:
print('press')
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setAcceptDrops(True)
button = Button('Button', self)
button.move(100, 65)
self.buttons = [button]
self.setWindowTitle('Copy or Move')
self.setGeometry(300, 300, 280, 150)
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
# get the relative position from the mime data
mime = e.mimeData().text()
x, y = map(int, mime.split(','))
if e.keyboardModifiers() & Qt.ShiftModifier:
# copy
# so create a new button
button = Button('Button', self)
# move it to the position adjusted with the cursor position at drag
button.move(e.pos()-QPoint(x, y))
# show it
button.show()
# store it
self.buttons.append(button)
# set the drop action as Copy
e.setDropAction(Qt.CopyAction)
else:
# move
# so move the dragged button (i.e. event.source())
e.source().move(e.pos()-QPoint(x, y))
# set the drop action as Move
e.setDropAction(Qt.MoveAction)
# tell the QDrag we accepted it
e.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
谢谢你的精彩回答。但是我仍然有疑问,为什么要将按钮移动到e.pos()-QtCore.QPoint(x,y)。e.pos()本身,是否给出了应该放置的位置。mimeData没有给出光标的位置,因为你已经将它设置为e.x()和e.y(),其中e是鼠标的位置,当我放下它时,e.pos()和QtCore.QPoint(x,y)不会同时出现。很抱歉,我不知道。@Manoj:
x
和y
来自mime
是光标相对于按钮的本地位置e.pos()
将是小部件上光标的实际位置(示例
)。如果要将按钮移动到e.pos()
,它会将按钮的左上角移动到该位置。例如,您选择了按钮中间的按钮。如果您仅使用e.pos()
移动到新的光标位置,按钮将不会按您拾取的方式放置,而是移动x,y
通过调整按钮的左上角来纠正该移位,使光标在落下后处于相同的位置。@Manoj:我猜您的混淆来自代码中的e.x()/e.y()
vse.pos()
。我得到e.x()/e.y()
的部分是按钮的mouseMoveEvent
。因此它们是相对于按钮的(0,0
位于左上方)。其中作为e.pos()
在示例的dropEvent
中。它给出的位置将是光标相对于示例的相对位置。是的,我现在理解了,谢谢你的时间。如果你也能帮我处理这段代码,那将非常好。抱歉发了垃圾邮件。