PyQt4 - Drag and Drop

匿名 (未验证) 提交于 2019-12-03 02:14:01

问题:

Hey I had been going through this tutorial for understanding drag and drop methods in PyQt4. However I am not able to understand the following points . It would be nice if somepne could make it clearer to me.

 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() 

Why is there are a seperate self.button.move() and e.setDropAction() Doesnt self.button.move() actually move the button itself? And could someone explain what drag.setHotSpot and drag.start() do? Thanks.

回答1:

That tutorial is seriously outdated. QDrag.start is obsolete since Qt 4.3. QDrag.exec_ should be used instead.

As you can see from the docs for exec, it has a return value. setDropAction in dropEvent determines this value. It doesn't perform the move. That's why you need a self.button.move() to do the actual moving. So, what's the point of a setDropAction? You might need to know what kind of drag operation you did. Imagine you're implementing drag-drop between two list widgets. If you did a move operation, that means you need to remove the item from the source widget and create one in the target. If it was a copy operation, you can leave the original and just create a copy in the target.

setHotSpot/hotSpot is related to the setPixmap of a QDrag. You can display a QPixmap as you drag the item. hotSpot determines the positioning of the pixmap. The pixmap will be positioned such that the cursor will be at hotSpot relative to the top-left corner of the pixmap. So, in the case of that tutorial, it is rather pointless since there is no pixmap to be shown.

Here is a bit modified and updated version of that tutorial. Hopefully, I've included enough comments. You can move with Right-Click or copy with Shift + Right-Click:

#!/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_()   


回答2:

Avaris' answer adapted for PyQt5 and 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_() 


文章来源: PyQt4 - Drag and Drop
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!