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

::-- zhuyj [2008-07-20 07:27:47]

1. Drag and Drop in PyQt4

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

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

    In computer graphical user interfaces, drag-and-drop is the action of (or support for the action of) clicking on a virtual object and dragging it to a different location or onto another virtual object. In general, it can be used to invoke many kinds of actions, or create various types of associations between two abstract objects. (Wikipedia)

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

    Drag and drop functionality is one of the most visible aspects of the graphical user interface. Drag and drop operation enables users to do complex things intuitively.

  • 拖放功能是最明显的图形用户接口外观,拖放操作允许用户直观的组合事物。

    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

简单的拖放

  • In the first example, we will have a QLineEdit and a QPushButton. We will drag plain text from the line edit widget and drop it onto the button widget.

  • 第一个例子中,我们有一个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)
  • In order to drop text on the QPushButton widget, we must reimplement some methods. So we create our own Button class, which will inherit from the QPushButton widget.

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

 self.setAcceptDrops(True)
  • We enable drop events for the QPushButton widget.

  • 我们允许QPushButton的放置事件。

   1  def dragEnterEvent(self, event):
   2      if event.mimeData().hasFormat('text/plain'):
   3          event.accept()
   4      else:
   5          event.ignore()
  • First we reimplement the dragEnteEvent() method. We inform about the data type, we will accept. In our case it is plain text.

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

   1  def dropEvent(self, event):
   2      self.setText(event.mimeData().text())
  • By reimplementing the dropEvent() method, we will define, what we will do upon the drop event. Here we change the text of the button widget.

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

 edit = QtGui.QLineEdit('', self)
 edit.setDragEnabled(True)
  • The QLineEdit widget has a built-in support for drag operations. All we need to do is to call setDragEnabled() method to activate it.

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

Simple Drag & Drop Figure: Simple Drag & Drop

1.2. Drag & drop a button widget

拖放按钮组件

  • In the following example, we will demonstrate, how to 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_()
  • In our code example, we have a QPushButton on the window. If we click on the button with a left mouse button, we print 'press' to the console. By right clicking and moving the button, we perform a drag & drop operation on the button widget.

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

   1  class Button(QtGui.QPushButton):
   2      def __init__(self, title, parent):
   3          QtGui.QPushButton.__init__(self, title, parent)
  • We create a Button class, which will derive from the QPushButton. We also reimplement two methods of the QPushButton. mouseMoveEvent() and mousePressEvent(). The mouseMoveEvent() method is the place, where the drag & drop operation begins.

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

 if event.buttons() != QtCore.Qt.RightButton:
     return
  • Here we decide, that we can perform drag & drop only with a right mouse button. The left mouse button is reserved for clicking on the button.

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

 mimeData = QtCore.QMimeData()
 drag = QtGui.QDrag(self)
 drag.setMimeData(mimeData)
 drag.setHotSpot(event.pos() - self.rect().topLeft())
  • Here we create a QDrag object.

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

 dropAction = drag.start(QtCore.Qt.MoveAction)
 if dropAction == QtCore.Qt.MoveAction:
     self.close()
  • The start() method of the drag object starts the drag & drop operation. If we perform a move drop action, we destory the button widget. Technically, we destroy a widget on the current position and recreate it on a new position.

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

   1  def mousePressEvent(self, event):
   2      QtGui.QPushButton.mousePressEvent(self, event)
   3      if event.button() == QtCore.Qt.LeftButton:
   4          print 'press'
  • . We print 'press' to the console, if we left click on the button with the mouse. Notice that we call mousePressEvent() method on the parent as well. Otherwise we would not see the button being pushed.

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

 position = event.pos()
 button = Button('Close', self)
 button.move(position)
 button.show()
  • In the dropEvent() method we code, what happens after we release the mouse button and finish the drop operation. In our example, we create a new Button widget at the current position of the mouse pointer.

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

 event.setDropAction(QtCore.Qt.MoveAction)
 event.accept()
  • We specify the type of the drop action. In our case it is a move action.

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

2. 交流

Name Password4deL ;) :( X-( B-)
viagra   hjnfmcpw ylfygekm gwtvenjs
2009-08-09 21:00:43
viagra prix   hmfwjlyr lwmcdhsi sbtysncn
2009-08-09 22:26:07
viagra prix   cjvcuqso ktiqwrqz wwmqpcsk
2009-08-09 23:52:10
viagra   qmlmplny prqohrof ffmwpbiy
2009-08-10 01:15:36
viagra   hnhgquua gxgjervo xanlvmqa
2009-08-10 02:38:57
cialis   rvtjktcu fnseikgg siahbves
2009-08-14 15:10:44
generique viagra   rnhlibyf ywadcafi ghgfigzh
2009-08-14 16:34:57
viagra   sarisalz evdfbqub iigvwggp
2009-08-14 17:59:01
cialis achat   btevbenq mafaetws vimvjpdx
2009-08-14 19:22:05
viagra france   wxmcopuq sfaqapmx tdlinrzp
2009-08-14 20:48:52
viagra   rckiixec vgewgnfd jepanhbi
2009-08-14 22:16:34
viagra   zpwdjois eulftgto kqcbllnl
2009-08-14 23:43:22
viagra   ljpvnsdk vrfmgwbl rcktxbjf
2009-08-15 01:09:48
cialis sur le net   rjkysmbo udpafgvc tzchshzv
2009-08-15 02:34:08
viagra vente   eetdxyhj zkfmsdjr ninevsel
2009-08-15 03:58:12
cialis rezeptfrei   idxkbajz uppirnct yamjfjxh
2009-08-18 13:39:21
viagra kaufen ohne r   knkleupp ncipysis wjguzwjf
2009-08-18 15:17:00
cialis bestellen   ugasasqg zgxmenyg wiidacqe
2009-08-18 16:58:09
viagra online   wauctwze llgwyaza hjiurszn
2009-08-19 16:02:30
acquisto viagra   hyhtopam bfnhxiod srbiamjm
2009-08-21 07:25:26
viagra   oyxeywnl ogtxfsaq obcijnvz
2009-08-21 19:20:53
acquisto cialis orig   wnjondme kwlpwjkb tmivzlxz
2009-08-22 01:19:04
acquisto viagra in f   pgjgdbfc wjjwuyxk mnthifvw
2009-08-22 05:45:03
acquisto cialis orig   niwlsyqf mskdtlcq ieiolruq
2009-08-22 11:44:44
cialis prix   chinqfgg oppuueol bbntxapo
2009-08-23 00:14:57
cialis 10mg   qymmhpux ultfhrxl lduyrigx
2009-08-23 02:02:18
cialis 10mg   xfeefcse xzzlwhhd dqplxliy
2009-08-23 03:45:56
acquisto viagra in f   pvzelbba tywsrmpi lkryjziy
2009-08-29 03:41:59
viagra sur le net   metogtcl xpmhbmbg rkcqicqi
2009-08-29 05:21:44
comprare cialis onli   fkxejshb hbzejlsb glbohovv
2009-08-29 06:58:13
comprare cialis in i   eqaogngt ywvstgto wkveotdg
2009-08-29 08:37:19
acquisto viagra   tphmwout qweknejd nmtrdevo
2009-08-29 10:18:05
comprare viagra senz   qliibmmd wynlloas sgwwmeii
2009-08-29 11:58:35
acquisto cialis orig   uwkrvawb uolomqaf zcpjoypj
2009-08-29 13:35:59
acquisto viagra   xnbrernu iqfnmogg mkxaseok
2009-08-29 15:12:52
cialis   kssswcaz jpbmaysh szvkgeoh
2009-08-29 16:51:48
viagra cialis   bcjjcjho eghdnuef bchwfcrq
2009-08-29 18:30:09