ちょっとした遊び心や、ツールの使い勝手や欲しい情報へのアクセス性などのUXの為に、Widgetが動かせたりするといいなーっと思ったことございませんか!?
そこで、PySideでマウスのイベントを上書きして、Widgetを動かせるようにする方法をご紹介したいと思います!(`・ω・´)ゞ
Classの骨格
サンプルの紹介として、見た目のわかりやすいQPushButtonを継承してDragで動くようにしていきたいと思います!
from PySide import QtCore, QtGui class DraggableButton(QtGui.QPushButton): def __init__(self, *args, **kwargs): super(DraggableButton, self).__init__(*args, **kwargs)
Dragした時にWidgetを動かくために、Drag中であるか判断するインスタンス変数「__isDrag」と、ドラッグを開始した座標を保存するインスタンス変数「__startPos」を用意します。
from PySide import QtCore, QtGui class DraggableButton(QtGui.QPushButton): def __init__(self, *args, **kwargs): super(DraggableButton, self).__init__(*args, **kwargs) self.__isDrag = False self.__startPos = QtCore.QPoint(0, 0)
Drag開始を検知する!
Drag開始を検知するには、「mousePressEvent」をオーバーライドします。Drag中であるステータスを「__isDrag」に設定し、マウスの座標を「__startPos」に記憶させます。
from PySide import QtCore, QtGui class DraggableButton(QtGui.QPushButton): def __init__(self, *args, **kwargs): super(DraggableButton, self).__init__(*args, **kwargs) self.__isDrag = False self.__startPos = QtCore.QPoint(0, 0) def mousePressEvent(self, event): self.__isDrag = True self.__startPos = event.pos() super(DraggableButton, self).mousePressEvent(event)
Drag終了を検知する!
Drag終了を検知するには、「mouseReleaseEvent」をオーバーライドします。Drag中であるステータスを「__isDrag」に設定し無駄に動かないようにします。
from PySide import QtCore, QtGui class DraggableButton(QtGui.QPushButton): def __init__(self, *args, **kwargs): super(DraggableButton, self).__init__(*args, **kwargs) self.__isDrag = False self.__startPos = QtCore.QPoint(0, 0) def mousePressEvent(self, event): self.__isDrag = True self.__startPos = event.pos() super(DraggableButton, self).mousePressEvent(event) def mouseReleaseEvent(self, event): self.__isDrag = False super(DraggableButton, self).mouseReleaseEvent(event)
Dragに合わせて動かす!
Drag中の処理は、「mouseMoveEvent」をオーバーライドします。「__isDrag」が「True」の場合だけ処理するようにします。
動かす量は、「Drag開始の座標」と「Drag先の座標」の差分から求められます。
だけど!
Widgetを動かせる「move」は親のWidgetを中心とするので、「mapToParent」で座標を変換してから動かします(*´∀`)b
from PySide import QtCore, QtGui class DraggableButton(QtGui.QPushButton): def __init__(self, *args, **kwargs): super(DraggableButton, self).__init__(*args, **kwargs) self.__isDrag = False self.__startPos = QtCore.QPoint(0, 0) def mousePressEvent(self, event): self.__isDrag = True self.__startPos = event.pos() super(DraggableButton, self).mousePressEvent(event) def mouseReleaseEvent(self, event): self.__isDrag = False super(DraggableButton, self).mouseReleaseEvent(event) def mouseMoveEvent(self, event): if self.__isDrag: self.move(self.mapToParent(event.pos() - self.__startPos)) super(DraggableButton, self).mouseMoveEvent(event)
テスト!
スタンドアローンのPythonでも平気ですが、ここではMayaを使って実験してみます!テストコードは以下のように、Windowを作ってDraggableButtonを設定します。
window = QtGui.QWidget() window.setWindowFlags(QtCore.Qt.Window) window.resize(1280, 720) layout = QtGui.QVBoxLayout(window) button = DraggableButton('DraggableButton', window) button.setFixedSize(128, 32) layout.addWidget(button) window.show()
実行して、ボタンをマウス(左・中・右)でドラッグしてみると、、、