Maya PySide2 / PySide チュートリアル 初級編 ② – .uiをMayaで表示する
このチュートリアルでは.uiをMaya上で表示する方法を学びます
準備
チュートリアルを始める前に__init__.py
とvtxMain.py
の二種類のpythonファイルを用意し、前回作成したsampleフォルダの中に入れてください
uiフォルダの中には前パートで作成した.uiファイルのvtxMain.ui
が保存されています
データ構成
C:\Users\\Documents\maya\scripts\sample\ui\vtxMain.ui
C:\Users\\Documents\maya\scripts\sample\__init__.py
C:\Users\\Documents\maya\scripts\sample\vtxMain.py
.uiのイメージ
WidgetはPySideのUIを構築するパーツの1単位で基本的にPySideのGUIはWidgetというGUIのパーツとなります
このPySideが標準で用意しているWidgetも分解してみれば複数のWidgetで構成されたテンプレートのGUIのようなものだったりします
つまり、.uiで構築したGUIもザックリととらえるとWidgetという1パーツとして捉えてもらっても差し支えがあまりないのです
複数の.uiを用意し、複数の.uiを大きな別のWidgetに入れ、GUIを構築するなんてことはよく用いることです
今回も似たような形でvtxMain.ui
というwidgetをQMainWindowというWidgetのCentralWigetという配置場所に表示してみます
Maya PySide2 / PySide チュートリアル 初学編 ⑤ – メインアプリケーションを作ろうでもQMainWindowについて触れましたがQMainWindowはアプリケーションのユーザーインターフェイスを構築するためのフレームワークを提供しており、 QToolBarやQDockWidgetなど追加できる独自のレイアウト機能が存在しています
今回のチュートリアルではそのあたりは触れませんがアプリケーションとして作成する際は便利なWidgetとなるため、カスタムしたWidgetをセットするという感覚に慣れてもらうためにあえてQMainWindowを使用してみます
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
try:
from PySide2.QtWidgets import *
from PySide2.QtCore import *
except ImportError:
from PySide.QtGui import *
from PySide.QtCore import *
class vtxMainWindow(QMainWindow):
def __init__(self, parent=None):
super(vtxMainWindow, self).__init__(parent)
self.setGeometry(500, 300, 400, 270)
self.setWindowTitle(.ui MainWindow)
def main():
app = QApplication.instance()
mainWin = vtxMainWindow()
mainWin.show()
sys.exit()
app.exec_()
上のコードをvtxMain.py
に記述してください
今回の例では、単純にQMainWindowが表示されるひな型になります
このUIをMaya上で使用するには下のコードをMayaのScript Editorで実行する必要があります
Script EditorはMayaの右下、上の画像のような位置にあるボタンから起動できます
起動すると下の画像のようなWindowが表示されるかと思います
そのWindowの中央にmelとpythonといった文字が書かれているtabがあるのでそのタブのpythonを選択しそこに下のコードをコピペして実行してください
import sample.vtxMain as vtxMain
reload(vtxMain)
vtxMain.main()
実行すると下の画像のような何もないWindowが表示されます
何も表示されずエラーが出たりする場合はscripの保存場所は名前の大文字小文字が間違っていたり、全角になっていたりするかもしれません
その場合は改めてデータ構成を確認してみてください
うまく起動ができた人は下のコードを追加してください
try:
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtUiTools import QUiLoader
except ImportError:
from PySide.QtGui import *
from PySide.QtCore import *
from PySide.QtUiTools import QUiLoader
このfrom PySide2.QtUiTools import QUiLoader
は.uiからGUIを構築するために使用するもので、QUiLoaderで.uiを読み込むには.uiのpathを知らなければなりません
詳細説明
QUiLoaderクラスを使用すると、スタンドアロンアプリケーションは、UIファイルに格納されている情報、またはプラグインパスで指定されている情報を使用して、実行時にユーザーインターフェイスを動的に作成できます
class vtxMainWindow(QMainWindow):
__currentPath = os.path.dirname(__file__)
__uiFilePath = os.path.join(__currentPath, ui, vtxMain.ui)
def __init__(self, parent=None):
super(vtxMainWindow, self).__init__(parent)
class vtxMainWindow(QMainWindow):
と def __init__(self, parent=None):
の間にクラス変数__currentPath
と__uiFilePath
を追加しました
__currentPath
はその名の通り、現在のpathという意味で__file__
のdirnameを指定しています__file__
はPythonで実行中のスクリプトファイル.pyの場所(パス)を取得することができるものですos.path.dirname()
はパス(文字列)を代入している変数から、フォルダ名(ディレクトリ名)を取得することが可能なメソッドになります
このos.path.dirname()
と__file__
の二つを組み合わせることで現在のpathを取得しています
そして、次に__uiFilePath
はその名の通り.uiファイルのpathになるのですがos.path.join
を使うことで引数に与えられた文字列を結合させ、一つのパスにすることを行っていますvtxMain.ui
はuiフォルダに格納しているので現在のパス、フォルダ名、uiファイル名を引数に指定することで.uiのpathを取得できるようにしています
class vtxMainWindow(QMainWindow):
__currentPath = os.path.dirname(__file__)
__uiFilePath = os.path.join(__currentPath, ui, vtxMain.ui)
def __init__(self, parent=None):
super(vtxMainWindow, self).__init__(parent)
loader = QUiLoader()
uiWidget = loader.load(self.__uiFilePath)
self.setCentralWidget(uiWidget)
self.setGeometry(500, 300, 400, 270)
self.setWindowTitle(.ui MainWindow)
次に.uiをQUiLoaderを使って読み込んでみます
.uiを読み込むにはQUiLoaderのload()使用しますloader = QUiLoader()
で変数名を宣言し、loader.load(self.__uiFilePath)
で呼び出した.uiをuiWidget
に入れます
そして、呼び出した.uiをQMainWindowのCentralWidgetにself.setCentralWidget(uiWidget)
でセットしています
この状態で再度Script Editorで呼び出すと下の画像のようにQt Designerで作成したGUIが表示されます
さてここで一つ大きな問題があります
それは表示したWindowがMayaのほかのUIを触れたり、ほかのソフトウェアなど表示したWindowからフォーカスが外れると突然Windowが消えてしまう問題です
これは消えているのではなくMayaのWindowの裏側に回っているだけで実際は消えていないのですがこれはこれでとても使いづらく、めんどくさく感じることでしょう
基本的にPySideで作成するWindowはMayaと親子関係を付けてあげる必要があります
そうしなければ後ろに回ってしまい使いにくいツールになってしまうからです
import maya.OpenMayaUI as OpenMayaUI
try:
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtUiTools import QUiLoader
import shiboken2 as shiboken
except ImportError:
from PySide.QtGui import *
from PySide.QtCore import *
from PySide.QtUiTools import QUiLoader
import shiboken
ptr = OpenMayaUI.MQtUtil.mainWindow()
mayaMainWindow = shiboken.wrapInstance(long(ptr), QMainWindow)
class vtxMainWindow(QMainWindow):
## 省略しています
def main():
app = QApplication.instance()
mainWin = vtxMainWindow(parent=mayaMainWindow)
mainWin.show()
sys.exit()
app.exec_()
import文にimport maya.OpenMayaUI as OpenMayaUI
とimport shiboken2 as shiboken
を追加しました
OpenMayaUI.MQtUtilはMayaのUIにアクセスするためのクラスでOpenMayaUI.MQtUtil.mainWindow()を使用することでMayaのメインウィンドウにアクセスしています
このままだと使用できないため、shiboken.wrapInstanceというものを使用してPySideで使えるようにします
詳しくはわからなくていいですがMayaのUI情報をいい感じに使えるようにする便利屋さんと思っていればいいです
使えるように加工したmayaMainWindow = shiboken.wrapInstance(long(ptr), QMainWindow)
をmainWin = vtxMainWindow(parent=mayaMainWindow)
でvtxMainWindowとMayaのMainWindowの親子関係をつけました
この状態で実行すると表示されたWindowが裏に回るということはなくなります。
詳しく
MayaにはmayaMixin.MayaQWidgetBaseMixin
というMayaとPySideの親子付けを簡単にできるクラスがあるのでこちらを使用してもいいのですがこのクラスが追加された次のバージョンかその次のバージョンのマイナーバージョンで突然使えないという不具合に悩まされたことがあるので基本的に上記のやり方を私は行っていますがこの辺はお好みでどうぞ
Maya PySide2 / PySide チュートリアルのこのパートでは、.uiをMaya上で表示させる方法を学びました
次はMaya PySide2 / PySide チュートリアル 初級編 ③ – GUIからMayaのコマンドを実行、BuddyやTab orderの設定方法
前はMaya PySide2 / PySide チュートリアル 初級編 ① – Qt Designer を使ってみる
ディスカッション
コメント一覧
まだ、コメントがありません