このチュートリアルは真剣に時代遅れです。 QDrag.start
はQt 4.3以降廃止されました。代わりにQDrag.exec_
を使用してください。
exec
のドキュメントからわかるように、戻り値があります。 setDropAction
をdropEvent
に設定すると、この値が決まります。それは移動を実行しません。そのため、実際に移動するにはself.button.move()
が必要です。だから、setDropAction
のポイントは何ですか?あなたがしたドラッグ操作の種類を知る必要があるかもしれません。 2つのリストウィジェット間でドラッグドロップを実装しているとします。移動操作を行った場合は、ソースウィジェットから項目を削除し、ターゲットに項目を作成する必要があることを意味します。コピー操作の場合は、元のままにして、ターゲットにコピーを作成するだけです。
setHotSpot
/は、QDrag
のsetPixmap
に関連しています。項目をドラッグすると、QPixmap
を表示することができます。 hotSpot
は、ピクスマップの位置を決定します。 pixmapは、カーソルがpixmapの左上隅を基準にしてhotSpot
になるように配置されます。したがって、このチュートリアルの場合は、表示するピクスマップがないので、無意味です。
ここでは、このチュートリアルの少し修正され、更新されたバージョンです。うまくいけば、私は十分なコメントを入れました。あなたはShift + Right-Click
と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_()
するようになっAvaris'答え素晴らしい答えをありがとう。しかし、私はまだ疑問があります。なぜボタンをe.pos() - QtCore.QPoint(x、y)に移動するのですか? e.pos()自身ではなく、落とすべき位置を指定しますか? 。そして、あなたがex()とey()にeを設定すると、マウスの位置がeであるので、e.pos()とQtCore.QPointの両方ではないので、mimeDataはカーソルの位置を与えません(x、y)である。申し訳ありませんが、私のnoobness。 – Manoj
@Manoj: 'mime'から来る' x'と 'y'は、ボタンのカーソルの_local position_です。 'e.pos()'はウィジェット上のカーソルの実際の位置になります( 'Example')。ボタンを 'e.pos()'に移動すると、ボタンの左上がその位置に移動します。たとえば、ボタンの中央にあるボタンを選択したとします。そして、 'e.pos()'だけで新しいカーソル位置に移動すると、ボタンはあなたがピックアップした方法ではなく配置されます。 'x、y'は、カーソルがドロップ後も同じ位置にくるように、ボタンの左上を調整することによってシフトを修正します。 – Avaris
@Manoj:あなたの混乱はコード内の 'e.x()/ e.y()' vs 'e.pos()'から来ていると思います。 'e.x()/ e.y()'を得る部分は 'Button'の' mouseMoveEvent'です。したがって、ボタンに相対的です(左上の「0,0」)。 'Example'の' dropEvent'に 'e.pos()'としています。それが与える位置は、 'Example'に対するカーソルの相対位置になります。 – Avaris