वह ट्यूटोरियल गंभीर रूप से पुराना है। Qt 4.3 से अप्रचलित है। इसके बजाय QDrag.exec_
का उपयोग किया जाना चाहिए।
जैसा कि आप exec
के लिए दस्तावेज़ों से देख सकते हैं, इसके पास वापसी मूल्य है। setDropAction
dropEvent
में यह मान निर्धारित करता है। यह कदम नहीं करता है। यही कारण है कि वास्तविक चलने के लिए आपको self.button.move()
की आवश्यकता है। तो, setDropAction
का बिंदु क्या है? आपको यह जानने की आवश्यकता हो सकती है कि आपने किस तरह का ड्रैग ऑपरेशन किया था। कल्पना करें कि आप दो सूची विजेट्स के बीच ड्रैग-ड्रॉप लागू कर रहे हैं। यदि आपने एक चाल ऑपरेशन किया है, तो इसका मतलब है कि आपको स्रोत विजेट से आइटम को निकालने और लक्ष्य में एक बनाने की आवश्यकता है। अगर यह एक प्रतिलिपि ऑपरेशन था, तो आप मूल छोड़ सकते हैं और केवल लक्ष्य में एक प्रति बना सकते हैं।
setHotSpot
/hotSpot
QDrag
के setPixmap
से संबंधित है। जब आप आइटम खींचते हैं तो आप QPixmap
प्रदर्शित कर सकते हैं। hotSpot
पिक्समैप की स्थिति निर्धारित करता है। पिक्समैप को इस प्रकार रखा जाएगा कि कर्सर hotSpot
पर पिक्समैप के ऊपरी-बाएं कोने के सापेक्ष होगा। तो, उस ट्यूटोरियल के मामले में, यह दिखाए जाने के लिए कोई पिक्समैप नहीं है क्योंकि यह व्यर्थ है।
यहां ट्यूटोरियल का थोड़ा संशोधित और अद्यतन संस्करण है। उम्मीद है कि, मैंने पर्याप्त टिप्पणियां शामिल की हैं। आप Right-Click
या प्रतिलिपि साथ स्थानांतरित कर सकते हैं 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_()
अद्भुत जवाब के लिए धन्यवाद के लिए अनुकूलित। हालांकि मुझे अभी भी संदेह है, मैं बटन को e.pos() - QtCore.QPoint (x, y) पर क्यों ले जाता हूं। E.pos() स्वयं नहीं है, यह स्थिति कहां छोड़ दी जानी चाहिए? । और mimeData कर्सर की स्थिति नहीं देता है क्योंकि आपने इसे पूर्व() और ey() पर सेट किया है, जहां ई माउस की स्थिति है, और जब मैं इसे छोड़ देता हूं, तो e.pos() और QtCore.QPoint दोनों नहीं होंगे (एक्स, वाई)। मेरे नोबनेस के लिए खेद है। – Manoj
@Manoj: 'mime' से आने वाला 'x' और' y' बटन के संबंध में कर्सर के _local position_ हैं। 'e.pos()' विजेट पर कर्सर की वास्तविक स्थिति होगी ('उदाहरण')। यदि आप बटन को 'e.pos()' पर ले जाना चाहते थे, तो यह उस स्थिति के बटन के ऊपरी-बाएं स्थानांतरित हो जाएगा। उदाहरण के लिए, आपने बटन के बीच में बटन उठाया। और यदि आप केवल 'e.pos()' के साथ नई कर्सर स्थिति में जाते हैं, तो बटन को आपके द्वारा उठाए गए तरीके से नहीं रखा जाएगा, बल्कि स्थानांतरित किया जाएगा। 'x, y' सही है कि बटन के ऊपरी-बाएं को समायोजित करके शिफ्ट करें कि कर्सर ड्रॉप के बाद एक ही स्थिति में होगा। – Avaris
@Manoj: मुझे लगता है कि आपका भ्रम कोड में 'e.x()/e.y()' बनाम 'e.pos()' से आता है। जिस हिस्से को मैं 'e.x()/e.y()' प्राप्त करता हूं वह 'बटन' का 'माउसमोवइवेंट' है। तो वे बटन के सापेक्ष हैं ('0,0' शीर्ष बाएं होने के नाते)। 'उदाहरण' के 'ड्रॉपएवेंट' में' e.pos() 'कहां से। यह स्थिति 'उदाहरण' के संबंध में कर्सर की सापेक्ष स्थिति होगी। – Avaris