Drag and Drop in PyQt4 PyQt4中的拖放操作

::-- ["zhuyj"] [DateTime(2008-07-20T07:27:47Z)] TableOfContents

1. Drag and Drop in PyQt4

"" In this part of the PyQt4 tutorial, we will talk about drag & drop operations.""

这部分PyQt4教程我们将了解拖放操作。

在计算机图形用户界面中,拖放操作是指点击一个虚拟对象并把它拖到一个不同的位置或其他的虚拟对象上的操作(或支持的行为).一般来说,可以调用多种操作,或创建两个抽象对象间的特定类型的关联。(Wikipedia)

Usually, we can drag and drop two things. Data or some graphical objects. If we drag an image from one application to another, we drag and drop binary data. If we drag a tab in Firefox and move it to another place, we drag and drop a graphical component.

1.1. Simple Drag and Drop

简单的拖放

第一个例子中,我们有一个QLineEdit和一个QPushButton。我们将从行编辑组件中拖动无格式的文本并将它放到按钮组件上。

   1 #!/usr/bin/python
   2 # dragdrop.py
   3 import sys
   4 from PyQt4 import QtGui
   5 class Button(QtGui.QPushButton):
   6     def __init__(self, title, parent):
   7         QtGui.QPushButton.__init__(self, title, parent)
   8         self.setAcceptDrops(True)
   9     def dragEnterEvent(self, event):
  10         if event.mimeData().hasFormat('text/plain'):
  11             event.accept()
  12         else:
  13             event.ignore()
  14     def dropEvent(self, event):
  15             self.setText(event.mimeData().text())
  16 class DragDrop(QtGui.QDialog):
  17     def __init__(self, parent=None):
  18         QtGui.QDialog.__init__(self, parent)
  19         self.resize(280, 150)
  20         self.setWindowTitle('Simple Drag & Drop')
  21         edit = QtGui.QLineEdit('', self)
  22         edit.setDragEnabled(True)
  23         edit.move(30, 65)
  24         button = Button("Button", self)
  25         button.move(170, 65)
  26 
  27 
  28         screen = QtGui.QDesktopWidget().screenGeometry()
  29         size =  self.geometry()
  30         self.move((screen.width()-size.width())/2,
  31             (screen.height()-size.height())/2)
  32 app = QtGui.QApplication(sys.argv)
  33 icon = DragDrop()
  34 icon.show()
  35 app.exec_()

   1  class Button(QtGui.QPushButton):
   2      def __init__(self, title, parent):
   3          QtGui.QPushButton.__init__(self, title, parent)

为了将文本放到QPushButton组件,我们必须重载一些方法,所以我们通过继承QPushButton组件来创建我们自己的按钮类。

 self.setAcceptDrops(True)

我们允许QPushButton的放置事件。

   1  def dragEnterEvent(self, event):
   2      if event.mimeData().hasFormat('text/plain'):
   3          event.accept()
   4      else:
   5          event.ignore()

首先我们重载dragEnteEvent()方法,我们通知我们将要收到的数据类型,这里是无格式文本。

   1  def dropEvent(self, event):
   2      self.setText(event.mimeData().text())

通过重载dropEvent()方法,我们定义我们收到drop事件后如何操作,这里我们改变按钮组件显示的文本。

 edit = QtGui.QLineEdit('', self)
 edit.setDragEnabled(True)

QLineEdit组件有内置的拖动操作,我们所要作的就是调用setDragEnabled()方法来接收它。

Simple Drag & Drop Figure: Simple Drag & Drop

1.2. Drag & drop a button widget

拖放按钮组件

以下的例子中我们将示范如何拖放一个按钮组件。

   1 #!/usr/bin/python
   2 # dragbutton.py
   3 import sys
   4 from PyQt4 import QtGui
   5 from PyQt4 import QtCore
   6 class Button(QtGui.QPushButton):
   7     def __init__(self, title, parent):
   8         QtGui.QPushButton.__init__(self, title, parent)
   9     def mouseMoveEvent(self, event):
  10 
  11         if event.buttons() != QtCore.Qt.RightButton:
  12             return
  13         mimeData = QtCore.QMimeData()
  14         drag = QtGui.QDrag(self)
  15         drag.setMimeData(mimeData)
  16         drag.setHotSpot(event.pos() - self.rect().topLeft())
  17         dropAction = drag.start(QtCore.Qt.MoveAction)
  18         if dropAction == QtCore.Qt.MoveAction:
  19             self.close()
  20     def mousePressEvent(self, event):
  21         QtGui.QPushButton.mousePressEvent(self, event)
  22         if event.button() == QtCore.Qt.LeftButton:
  23             print 'press'
  24 class DragButton(QtGui.QDialog):
  25     def __init__(self, parent=None):
  26         QtGui.QDialog.__init__(self, parent)
  27         self.resize(280, 150)
  28         self.setWindowTitle('Click or Move')
  29         self.setAcceptDrops(True)
  30         self.button = Button('Close', self)
  31         self.button.move(100, 65)
  32 
  33 
  34         screen = QtGui.QDesktopWidget().screenGeometry()
  35         size =  self.geometry()
  36         self.move((screen.width()-size.width())/2,
  37             (screen.height()-size.height())/2)
  38     def dragEnterEvent(self, event):
  39          event.accept()
  40     def dropEvent(self, event):
  41         position = event.pos()
  42         button = Button('Close', self)
  43         button.move(position)
  44         button.show()
  45         event.setDropAction(QtCore.Qt.MoveAction)
  46         event.accept()
  47 app = QtGui.QApplication(sys.argv)
  48 db = DragButton()
  49 db.show()
  50 app.exec_()

在我们的例子里,窗口有一个QPushButton,如果我们鼠标左键点击按钮,我们在终端上打印'press',如果我们右键点击并拖动按钮,我们对按钮组件执行拖放操作。

   1  class Button(QtGui.QPushButton):
   2      def __init__(self, title, parent):
   3          QtGui.QPushButton.__init__(self, title, parent)

我们创建一个起源自QPushButton的按钮类。我们同时重载QPushButton的两个方法mouseMoveEvent()和mousePressEvent()。mouseMoveEvent()方法是拖放操作开始的位置。

 if event.buttons() != QtCore.Qt.RightButton:
     return

这里我们设定只对鼠标右键的拖放操作作出响应,对鼠标左键操作保留给点击按钮。

 mimeData = QtCore.QMimeData()
 drag = QtGui.QDrag(self)
 drag.setMimeData(mimeData)
 drag.setHotSpot(event.pos() - self.rect().topLeft())

这里我们创建一个QDrag对象。

 dropAction = drag.start(QtCore.Qt.MoveAction)
 if dropAction == QtCore.Qt.MoveAction:
     self.close()

拖动对象的start()方法开始拖放操作。如果我们完成一次移动放置操作,我们要销毁按钮组件。技术上来讲,我们在当前位置销毁一个组件,并在新位置重新创建它。

   1  def mousePressEvent(self, event):
   2      QtGui.QPushButton.mousePressEvent(self, event)
   3      if event.button() == QtCore.Qt.LeftButton:
   4          print 'press'

如果我们点击鼠标左键,就在控制台打印'press'。注意,这里我们调用了父类的mousePressEvent()方法,否则我们无法看到鼠标被按下的效果。

 position = event.pos()
 button = Button('Close', self)
 button.move(position)
 button.show()

在dropEvent()方法中包含了当我们释放鼠标按键并且结束放置后的操作的代码。在我们的例子里,我们在鼠标指针的当前位置创建了一个新的按钮组件。

 event.setDropAction(QtCore.Qt.MoveAction)
 event.accept()

我们指定释放操作的类型。这里是移动操作。

2. 交流

PageComment2