PyQt4中的拖放
点击此处查看原文。
在本文中,我们主要谈谈PyQt4中的拖放(drag & drop)操作。
在计算机图形用户界面中,拖放(drag-and-drop)是点击一个虚拟对象并且拖动到另一位置或虚拟对象之上的一个动作。以来来说,它可以用于调用多种不同的动作,或者创建两个抽象类型对象之间的关联。
拖放是图用用户界面的一部分。拖放操作允许用户更直观地做复杂的事情。
通常,我们可以拖放两种事物:数据和一些图形对象。当我们在不同应用程序之间拖放图片时,我们实际上拖放的是二进制数据;当我们在firefox中将一个标签移动到另一个点方时,我们拖放的是一个图形组件。
1 简单的拖放
在第一个示例程序中,我们分别创建了QtGui.QLineEdit和QtGui.QPushButton对象,当我们将编辑框控件的文本拖放到按钮控件上时,改变按钮的文本内容。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui
class Button(QtGui.QPushButton):
def __init__(self, title, parent):
super(Button, self).__init__(title, parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()
def dropEvent(self, e):
self.setText(e.mimeData().text())
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
edit = QtGui.QLineEdit('', self)
edit.setDragEnabled(True)
edit.move(30, 65)
button = Button('Button', self)
button.move(190, 65)
self.setWindowTitle('Simple drag & drop')
self.setGeometry(300, 300, 300, 150)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
上面的示例展示了一个简单的拖放操作。
为了将文本内容拖放到QtGui.QPushButton控件上,我们必须重新实现该类的一些方法。因此,我们通过继承QtGui.QPushButton类,从而创建属于我们自己的按钮Button类。
class Button(QtGui.QPushButton):
def __init__(self, title, parent):
super(Button, self).__init__(title, parent)
同时,我们为该控件启用drop事件。
self.setAcceptDrops(True)
首先,我们重新实现dragEnterEvent()方法。通知我们需要接收的数据类型,在该示例程序中是明文文本(plain text)。
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()
接下来,通过重新实现dropEvent()方法,定义当drop事件到达时,将采取何种操作。在此处,我们只是改变按钮控件的文本。
def dropEvent(self, e):
self.setText(e.mimeData().text())
QtGui.QLineEdit控件内置支持拖拽(drag)操作。我们所要做的就是调用setDragEnable()方法激活它。
edit = QtGui.QLineEdit('', self)
edit.setDragEnable(True)
2 拖放按钮控件
在接下来的示例中,我们将展示如何拖放按钮控件。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
class Button(QtGui.QPushButton):
def __init__(self, title, parent):
super(Button, self).__init__(title, parent)
def mouseMoveEvent(self, e):
if e.buttons() != QtCore.Qt.RightButton:
return
mimeData = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
dropAction = drag.start(QtCore.Qt.MoveAction)
def mousePressEvent(self, e):
super(Button, self).mousePressEvent(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)
self.button = Button('Button', self)
self.button.move(100, 65)
self.setWindowTitle('Click or Move')
self.setGeometry(300, 300, 280, 150)
self.show()
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
position = e.pos()
self.button.move(position)
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
在上面的示例程序中,我们创建了一个按钮,当我们使用鼠标左键点击单击按钮时,控制台会显示‘press’消息;通过单击鼠标右键并移动,我们可以执行按钮控件的拖放操作。
我们通过派生自QtGui.QPushButton类创建了一个新的Button类,在该类中,我们重新实现了QtGui.QPushButton类的两个方法:mouseMoveEvent()和mousePressEvent()。mouseMoveEvent()方法是放置拖放操作开始的地方。
class Button(QtGui.QPushButton):
def __init__(self, title, parent):
super(Button, self).__init__(parent)
我们执行拖放操作当且仅当鼠标按下时执行。鼠标左键保留给按钮点击。
if e.buttons() != QtCore.Qt.RightButton:
return
创建QDrag对象,该对象提供了执行基于MIME(MIME-based)的拖放传输。
mimeData = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
drag对象的start()方法用于执行拖放的开始操作。
dropAction = drag.start(QtCore.Qt.MoveAction)
当我们点击鼠标左键时,在控制台显示‘press’消息。此外,需要注意的是我们调用的是父类的mousePressEvent()方法。如果不这样做,我们看不到按钮被按下。
def mousePressEvent(self, e):
super(Button, self).mousePressEvent(e)
if e.button() == QtCore.Qt.LeftButton:
print 'press'
在dropEvent()方法中,我们指定鼠标释放时执行的动作并且完成拖放操作。我们获取当前鼠标的位置并对按钮进行相应的移动。
position = e.pos()
self.button.move(position)
接下来指定放置动作(drop action)的类型。在我们的示例中他是移动动作(move action)。
总结
在上文中,主要谈到了PyQt4中拖放操作的一些基础知识,包括文本的拖放以及组件的拖放。实际生产中拖放远比上述两个示例复杂,针对不同类型对象需要指定拖放时的数据类型。上面的示例中只是简单地提到了几种类型操作。