【Maya Python】QtDesignerで作成した.uiをMayaで表示する

#はじめに
[【Maya Python】スクリプトの中身を噛み砕く1](https://qiita.com/elloneil/items/56591ab00c2a9b66ce2a)、[2](https://qiita.com/elloneil/items/b84d39767760086f48a7)、[3](https://qiita.com/elloneil/items/3f4a47501204af16cd0a)で書いたスクリプトの書き方では小さいスクリプトでは問題ありませんが、複雑なUIを作ろうとすると大変な労力がかかります。
そこで[QtDesigner](https://build-system.fman.io/qt-designer-download)を使用しUIを組み立ててみようと思います。
CGアーティストとしてはスクリプトで悩むよりこういったわかりやすいツールがあるといいですね。
今回はとりあえず触ってみて感じを掴むためにMayaでUIを表示して簡単な動作をさせるところまで作ってみたいと思います。
PySideとPySide2、PyQt5などやり方が散見されているので自分の備忘録も兼ねて書きます。
動作環境はMaya2019,2020です。

#UIファイルを用意する
とりあえずこんな感じにUIを作ってみました。
![UI.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507736/d990b6f7-f42e-b3ed-a114-751a125542d4.jpeg)

作り方についてはこちらのサイトを参考。
> [PyQt5とpython3によるGUIプログラミング：実践編[0]](https://qiita.com/kenasman/items/b9ca3beb25ecf87bfb06#combobox%E3%81%A7%E5%AE%9F%E9%A8%93)
[第5章 Qt Designerを使ってみよう](https://densan-labs.net/tech/qt/chapter5.html)
[QtDesignerでUIを作る](https://fereria.github.io/reincarnation_tech/11_PySide/01_PySide_Basic/00_Tutorial/02_create_designer/)

###少し詰まったところをメモ
**レイアウトの設定をしっかりやる**
そのまま配置しただけだと、ウィンドウサイズを変更してもUIが追従してくれなかったり、ウィンドウ立ち上げ時にウィンドウが小さすぎるなど起こってしまう。
![ui01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507736/f341c782-6245-2b23-1350-0057359de8ee.jpeg)
図のようにcentralwidgetがbrakeLayoutになっていると全部表示してくれない。
![ui02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507736/4171b272-9ceb-435f-8cef-93115274b51a.jpeg)
レイアウトを設定し、ウインドウサイズを調整後、Size Constraintsで最小サイズを設定する。するとちゃんと収まった状態のウィンドウを作ることができる。ウィンドウサイズを変更してもUIが追従してくれる。
![ui03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507736/bb2d6048-e7cc-2e29-8a8a-82701f55f183.jpeg)
レイアウト設定後の初期起動時図

#ウィンドウを表示するプログラムを用意する
ひとまずコード全文

```python
# -*- coding: utf-8 -*-
from PySide2 import QtWidgets
from PySide2.QtUiTools import QUiLoader
from maya.app.general.mayaMixin import MayaQWidgetBaseMixin

# パスを直接指定
UIFILEPATH = 'C:/Users/YN/Desktop/testUI.ui'

## MainWindowを作るクラス
class MainWindow(MayaQWidgetBaseMixin, QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        # UIのパスを指定
        self.UI = QUiLoader().load(UIFILEPATH)
        # ウィンドウタイトルをUIから取得
        self.setWindowTitle(self.UI.windowTitle())
        # ウィジェットをセンターに配置
        self.setCentralWidget(self.UI)

        # ボタンを接続
        self.UI.refreshPushButton.clicked.connect(self.refreshPushButton)

    def refreshPushButton(self):
        print ('refresh')

## MainWindowの起動
def main():
    window = MainWindow()
    window.show()

if __name__ == '__main__':
    main()

```

スクリプトエディターにコピペして、
`UIFILEPATH`を先ほど作成したuiのパスに設定します。
そして実行すればひとまず作成したUIをMayaで確認できます。
![ui04.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507736/c1584fbf-a34e-d46d-70e1-24a45e4dde5c.jpeg)

#プログラム詳細
###UIをロード
`from PySide2.QtUiTools import QUiLoader`
UIをロードするには`QtUiTools`から`QUiLoader`をインポートします。

`self.UI = QUiLoader().load(UIFILEPATH)`
`UIFILEPATH`を読み込み、`self.UI`としてインスタンスします。

###UIから値を取得
`self.setWindowTitle(self.UI.windowTitle())`
ウィンドウタイトルを指定しないと適当な名前でウィンドウが作成されるためウィンドウタイトルを作成したUIファイルから取得します。もちろんここに`string`で入力することも可能です。
`self.UI.windowTitle()`
UIの中のプロパティ名を指定すればそこに設定されている値を取得できます。
![ui05.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507736/0b84bfc1-60fb-fbe7-0b5a-fbfa904c1a45.jpeg)
このように設定しておけばプログラムで書き換えずともUIファイルを変更すればいいので便利です。

###UIを配置
`self.setCentralWidget(self.UI)`
UIを配置します。

###ボタンの動作を作成
`self.UI.refreshPushButton.clicked.connect(self.refreshPushButton)`
objectNameが`refreshPushButton`のボタンに、クリックしたときの機能を接続します。
![ui06.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507736/5e069cb6-bac6-2baf-c75b-7aee25351a53.jpeg)
このようにQtDesignerでオブジェクト名を指定しておきます。

```python
    def refreshPushButton(self):
        print ('refresh')
```
ボタンを押したときに、refreshとプリントするような機能をつけました。
実際は、ここにこのボタンに設定したい機能を書き込んで行きます。

#おわりに
私も、はじめはどこから手を付ければいいか暗中模索状態だったので、なにかの役に立てればと思います。
MayaでとりあえずサクッとUI表示してあー、こうなってるのねというのがわかってくればどんどんUIを複雑にしていけるんじゃないでしょうか。

MayaのPySide2は途中でPySideからアップデートがあり、記述の仕方が変わったため混乱しました。また似たようなPyQt5など検索にヒットしてしまうため更にややこしいですね。。

#参考
大変参考になりました。ありがとうございます。
> [PyQt5とpython3によるGUIプログラミング：実践編[0]](https://qiita.com/kenasman/items/b9ca3beb25ecf87bfb06#combobox%E3%81%A7%E5%AE%9F%E9%A8%93)
[第5章 Qt Designerを使ってみよう](https://densan-labs.net/tech/qt/chapter5.html)
[QtDesignerでUIを作る](https://fereria.github.io/reincarnation_tech/11_PySide/01_PySide_Basic/00_Tutorial/02_create_designer/)