QtDesignerで配置後にPython上でのWidgetのカスタマイズ
ファイル
https://drive.google.com/file/d/0B4fmLEFqtND0THd4TmlDR0lQems/view?usp=sharing
QtDesigner上でこんな感じのUIを作成したとして
このUIに対して
- ボタンを動かせるようにする
- GrapshicsView(以下View)にボタンが当たったら色を変える
という処理を追加する場合、ボタンとView用のWrapperクラスを作成する。
ButonWrapper
class ButtonWrapper(WrapperBase): collision = QtCore.Signal(WrapperBase) def __init__(self, widget, col): """ :type widget: PySide.QtGui.QWidget """ super(ButtonWrapper, self).__init__(widget) #: :type: QColor self.__color = col #: :type: WrapperBase self.__collision_target = None self.widget.mousePressEvent = self.__on_pressed self.widget.mouseMoveEvent = self.__on_moved self.__move_offset = None pass @property def color(self): return self.__color def __on_pressed(self, event): """ :type event: PySide.QtGui.QMouseEvent """ self.__move_offset = self.widget.mapFromGlobal(event.globalPos()) pass def __on_moved(self, event): """ :type event: PySide.QtGui.QMouseEvent """ pos = self.widget.window().mapFromGlobal(event.globalPos()) pos -= self.__move_offset self.widget.move(pos.x(), pos.y()) if self.__collision_target and self.__collision_target.widget.geometry().intersects(self.widget.geometry()): self.collision.emit(self) pass def set_collision_target(self, wrapper): """ :type wrapper: ButtonWrapper """ self.__collision_target = wrapper pass
ViewWrapper
class ViewWrapper(WrapperBase): def __init__(self, widget): """ :type widget: PySide.QtGui.QWidget """ super(ViewWrapper, self).__init__(widget) self.widget.enterEvent = self.__on_enter self.widget.leaveEvent = self.__on_leave pass def __on_enter(self, event): print "mouse enter." pass def __on_leave(self, event): print "mouse leave." pass def set_color(self, color): scene = QtGui.QGraphicsScene() scene.setBackgroundBrush(color) self.widget.setScene(scene) pass
基本的には、両方とも__init__のwidgetにはQtDesigner上で配置されたWidgeを指定し、
その中のVirtualFunctionを書き換えるような処理を行っている。
(ぶっちゃけこのVirtualFunctionを書き換えられれば良いのでWrapperクラスとか作らなくていい)
ButonWrapper
self.widget.mousePressEvent = self.__on_pressed self.widget.mouseMoveEvent = self.__on_moved
ViewWrapper
self.widget.enterEvent = self.__on_enter self.widget.leaveEvent = self.__on_leave
書き換えられるVirtualFunctionについてはPySideの公式Referenceを読めばわかる。
MayaのPySideのバージョンは1.2らしいので1.2.1のRefernceあたりを見ればいいと思う。
個人的には1.2.1のRefernceだと図でクラスをたどれないので1.0.1が好き。
本来であれば
- QWidgetなり継承してVirtualFunctionをオーバーライド、それをQtDesignerで格上げ先として
使えるようにする - QtCreator(C++)で最終的なuiファイルまで作成してそれをPythonで使う(出来るか不明)
が正しいのだろうけど自分の頭では無理だった・・・。
ついでにWidget同士の当たり判定について
処理部分はここ↓
ButtonWraper
if self.__collision_target and self.__collision_target.widget.geometry().intersects(self.widget.geometry()): self.collision.emit(self) pass
widgetからgeometry()でQRectを取得してそれをintersectsで判定している。
rect()から取得したQRectの場合、位置が来ないらしく正しい判定ができなかった。