Drag&Dropでデータの受け渡しをする方法!!

takkun
どうも!たっくんです!
なかなか風邪が治らない、、、orz

せっかくPySideでUIを作るなら、D&Dでやりとりしてデータの受け渡しができるようにしたいですよね!

今回は、WidgetをDragしてQLineEditにDropするとテキストの受け渡しができる方法をご紹介したいと思います!∠( ゚д゚)/

D&Dの類似する記事も、是非あわせてどうぞ!

QListViewにファイルをD&Dする!!

2017.05.02

PySideでMaya内のD&Dを受け取る方法!!

2017.08.09

DragできるQLabelの用意

まずは、DragできるQLabelを用意したいと思います!味付けで、テキストをセンタリングして、背景色が黒になるようにしています!

from PySide import QtCore, QtGui

class DraggableLabel(QtGui.QLabel):
	def __init__(self, *args, **kwargs):
		super(DraggableLabel, self).__init__(*args, **kwargs)
		
		# テキストのセンタリング
		self.setAlignment(QtCore.Qt.AlignCenter)
		
		# 背景色を黒に設定
		palette = self.palette()
		palette.setColor(self.backgroundRole(), QtCore.Qt.black)
		self.setPalette(palette)
		self.setAutoFillBackground(True)

Dragにデータを仕込む!

DraggableLabel」がDragされた時に、表示されているテキストのデータを仕込むようにしたいと思います。

mousePressEvent」をオーバーライドして、データのやり取りで使う「QMimeData」をDragに設定します。(`・ω・´)ゞ

from PySide import QtCore, QtGui

class DraggableLabel(QtGui.QLabel):
	def __init__(self, *args, **kwargs):
		super(DraggableLabel, self).__init__(*args, **kwargs)
		
		self.setAlignment(QtCore.Qt.AlignCenter)
		
		palette = self.palette()
		palette.setColor(self.backgroundRole(), QtCore.Qt.black)
		self.setPalette(palette)
		self.setAutoFillBackground(True)
		
	def mousePressEvent(self, event):
		super(DraggableLabel, self).mousePressEvent(event)
		
		# Mimeデータを作成して、QLabelのテキストを設定する
		mimeData = QtCore.QMimeData()
		mimeData.setText(self.text())
		
		# Dragオブジェクトを作成して、データを設定する
		drag = QtGui.QDrag(self)
		drag.setMimeData(mimeData)
		
		# Dragを実行して、ユーザーがマウスを離すまで待機
		drag.exec_()

Dropを受け付けるQLineEditの用意

続いて、Dropを受け付けるQLineEditを用意します。Dropを受け付けられるように「setAcceptDrops」を忘れず設定します。

from PySide import QtCore, QtGui

class DraggableLabel(QtGui.QLabel):
	def __init__(self, *args, **kwargs):
		super(DraggableLabel, self).__init__(*args, **kwargs)
		
		self.setAlignment(QtCore.Qt.AlignCenter)
		
		palette = self.palette()
		palette.setColor(self.backgroundRole(), QtCore.Qt.black)
		self.setPalette(palette)
		self.setAutoFillBackground(True)
		
	def mousePressEvent(self, event):
		super(DraggableLabel, self).mousePressEvent(event)
		
		mimeData = QtCore.QMimeData()
		mimeData.setText(self.text())
		
		drag = QtGui.QDrag(self)
		drag.setMimeData(mimeData)		
		drag.exec_()
		
class DroppableLineEdit(QtGui.QLineEdit):
	def __init__(self, *args, **kwargs):
		super(DroppableLineEdit, self).__init__(*args, **kwargs)
		
		# Dropを受け付ける
		self.setAcceptDrops(True)

データを取り出す!

Dropされたときの動作を変更するには「dropEvent」をオーバーライドします。テキスト情報を取り出には、「event」の「QMimeData」からアクセスしていきます(*´ω`*)b

from PySide import QtCore, QtGui

class DraggableLabel(QtGui.QLabel):
	def __init__(self, *args, **kwargs):
		super(DraggableLabel, self).__init__(*args, **kwargs)
		
		self.setAlignment(QtCore.Qt.AlignCenter)
		
		palette = self.palette()
		palette.setColor(self.backgroundRole(), QtCore.Qt.black)
		self.setPalette(palette)
		self.setAutoFillBackground(True)
		
	def mousePressEvent(self, event):
		super(DraggableLabel, self).mousePressEvent(event)
		
		mimeData = QtCore.QMimeData()
		mimeData.setText(self.text())
		
		drag = QtGui.QDrag(self)
		drag.setMimeData(mimeData)		
		drag.exec_()
		
class DroppableLineEdit(QtGui.QLineEdit):
	def __init__(self, *args, **kwargs):
		super(DroppableLineEdit, self).__init__(*args, **kwargs)
		self.setAcceptDrops(True)
		
	def dropEvent(self, event):
		# テキスト情報が埋め込まれているか確認
		if event.mimeData().hasText():
			# テキスト情報を取り出し設定する。
			self.setText(event.mimeData().text())
			event.accept()

実験!

以下のコードで早速実験してみます!

widget = QtGui.QWidget()
widget.setWindowFlags(QtCore.Qt.Window)
widget.resize(640, 72)

mainLayout = QtGui.QVBoxLayout(widget)
mainLayout.addWidget(DroppableLineEdit())

layout = QtGui.QHBoxLayout(widget)
mainLayout.addLayout(layout)

layout.addWidget(DraggableLabel('persp'))
layout.addWidget(DraggableLabel('top'))
layout.addWidget(DraggableLabel('front'))
layout.addWidget(DraggableLabel('side'))
widget.show()

黒い背景のLabelを、入力欄にD&Dするとテキスト情報のやりとりがされます!(`・ω・´)ゞ