2013/05/25

[PySide] mayaのFrameLayoutを自作する

maya でツール作ってる人なら共感出来ると思うのですが
QtGui に FrameLayout(※) が無いんです|ω・`)

なんで無いんですか



なんで無いんですか!


…と、同じこと何度も言ってても仕方が無いので、無いものは作ればいいんです!

※FrameLaout:タイトルバーを押すと中身のUIを開閉出来るので mayaUI で多用されるかなり便利な部品



QtDesigner でレイアウト



以下の画像のように、押すと開閉出来るボタンは QToolButton で、
開閉される中身は QFrame で作り、QVBoxLaout で並べて置きます
それ以外は好きなものを詰め込んでください

※この例では解説用にマージンがかなり多めに付けてありますが、適度に調整してください


なぜ QToolButton を使うかというと、QPushButton には無い Arrow(矢印アイコン)が出せるからです
プロパティエディタでこのように設定してあげてください

アイコンサイズはデフォルトだとでかいからですw



FrameLayout のクラスを作る


開閉する操作は QtDesigner のシグナル設定だけだと難しいので自前で書きます
といっても、基本的な動作は数行で済みます
# -*- coding: utf-8 -*-

import os
import sys

from PySide import QtCore, QtGui
from PySide.QtUiTools import QUiLoader

CURRENT_PATH = os.path.dirname(__file__)

#----------------------------------------------------------------------------
## FrameLayoutを作るクラス
class FrameLayout(object):

    def __init__(self, titleBar, frame):
        self.titleBar = titleBar    # 上のボタンウィジェット
        self.frame = frame          # 開閉するウィジェット
        self.collapse = False       # 開閉している状態フラグ
        self.setSignals()           # シグナルをセット

    #-------------------------------------------------------------------------
    ## シグナルを設定する
    def setSignals(self):
        self.titleBar.clicked.connect(self.setCollapse)

    #-------------------------------------------------------------------------
    ## フレームを開閉するアクション
    def setCollapse(self):
        # 現在のステータスを反転する
        self.collapse = not self.collapse
        # フレームのビジビリティを変更する
        self.frame.setHidden(self.collapse)

        # 開閉状況に合わせてアロータイプを変更する
        if self.collapse:
            # 閉じている時は右に向ける
            self.titleBar.setArrowType(QtCore.Qt.RightArrow)
        else:
            # 開いている時は下へ向ける
            self.titleBar.setArrowType(QtCore.Qt.DownArrow)


#----------------------------------------------------------------------------
## GUIを作るクラス
class GUI(QtGui.QMainWindow):

    def __init__(self, parent=None):
        super(GUI, self).__init__(parent)
        loader = QUiLoader()
        uiFilePath = os.path.join(CURRENT_PATH, 'frameLayout.ui')
        self.UI = loader.load(uiFilePath)
        self.setCentralWidget(self.UI)

        # フレームレイアウトにするクラスに渡す
        self.frameLayout = FrameLayout(self.UI.toolButton, self.UI.frame)

#------------------------------------------------------------------------------
## GUIの起動
def main():
    app = QtGui.QApplication(sys.argv)
    app.setStyle('plastique')    # ← ここでスタイルを指定
    ui = GUI()
    ui.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

#-----------------------------------------------------------------------------
# EOF
#-----------------------------------------------------------------------------

いつもの感じで実行すると、こんな感じになります
(実行の仕方は、過去の記事 を参考にしてみてください)


さぁ、思う存分パカパカするがよい! フハハハ