コンテンツにスキップ

single UI & parent UI をまとめて実現

■パターン1

  • 1つのpythonファイルで完結コーディング の場合
1 pythonファイル
# -*- coding: utf-8 -*-

# OK: parent UI 実現
# OK: single UI 実現

from PySide2 import QtCore, QtGui, QtWidgets
from maya import OpenMayaUI as omUI
import shiboken2


# parent UI 実現の準備
# OpenMayaUIに、Qtに関する補助機能が用意されています。これはPythonからでも利用できますが、「C++」の
# 「ポインタ※」という機能がPython には無いため、そのままでは使用できません。そこで、C++ で作られた機能
# をPythonから使えるようにしてくれる、PySide付属のモジュール「shiboken」を使用して対応していきます。
# 「shiboken」の中には、「wrapInstance」という機能があり、C++ のポインタの情報をPython で扱えるデータ
# に変換してくれます。コレを使ってポインタからQWidget に変換したデータを、呼び出された場所に「return」を
# 使用して返します。
# 「ポインタ」とは、データがメモリのどこに保存されているか、住所を表すものです。
def getMayaWindow():  # Maya のウィンドウを取得する関数です 
    """
    Get the main Maya window as a QtGui.QMainWindow instance
    @return: QtGui.QMainWindow instance of the top level Maya windows
    """
    ptr = omUI.MQtUtil.mainWindow()
    if ptr is not None:
        return shiboken2.wrapInstance(long(ptr), QtWidgets.QMainWindow)


class testUI(QtWidgets.QDialog):
    def __init__(self):
        # parent UI
        super(testUI, self).__init__(getMayaWindow())

        self.setWindowTitle('test UI')

        # すでにUIが出来てる場合は削除する #
        # MayaのMainWindowの子Windowを取得
        child_list = self.parent().children()
        for c in child_list:
            # 自分と同じ名前のUIのクラスオブジェクトが存在してたらCloseする
            if self.__class__.__name__ == c.__class__.__name__:
                c.close()
        # ------------------------ #
        btn = QtWidgets.QPushButton("Hello World")
        layout = QtWidgets.QVBoxLayout()

        layout.addWidget(btn)
        self.setLayout(layout)


def main():
    mainWindow = getMayaWindow()
    nowExists = mainWindow.findChildren(testUI)

    # single UI
    # findChildrenで、指定クラスの子を探すのではなく
    # 全ての子オブジェクトのクラス名で判定して、同じなら閉じるようにすれば
    # reloadしようがScriptEditorで実行しようが問題ない。
    for i in nowExists:
        i.close()

    win = testUI()
    win.show()


if __name__ == '__main__':
    print(u'{}.py: loaded as script file'.format(__name__))
    main()
else:
    print(u'{}.py: loaded as module file'.format(__name__))

print(u'モジュール名:{}'.format(__name__))  # 実行したモジュール名を表示する


  • pythonファイルを分けてコーディング の場合

例えば、
lib フォルダ
├ __init__.py
└ qt.py
として、

2 pythonファイル
qt.py
# -*- coding: utf-8 -*-

# parent UI 実現の準備

from maya import OpenMayaUI, cmds
from PySide2 import QtWidgets, QtCore, QtGui
import shiboken2


# parent UI 実現の準備
# OpenMayaUIに、Qtに関する補助機能が用意されています。これはPythonからでも利用できますが、「C++」の
# 「ポインタ※」という機能がPython には無いため、そのままでは使用できません。そこで、C++ で作られた機能
# をPythonから使えるようにしてくれる、PySide付属のモジュール「shiboken」を使用して対応していきます。
# 「shiboken」の中には、「wrapInstance」という機能があり、C++ のポインタの情報をPython で扱えるデータ
# に変換してくれます。コレを使ってポインタからQWidget に変換したデータを、呼び出された場所に「return」を
# 使用して返します。
# 「ポインタ」とは、データがメモリのどこに保存されているか、住所を表すものです。
def getMayaWindow():  # Maya のウィンドウを取得する関数です
    """
    Get the main Maya window as a QtGui.QMainWindow instance
    @return: QtGui.QMainWindow instance of the top level Maya windows
    """
    ptr = OpenMayaUI.MQtUtil.mainWindow()
    if ptr is not None:
        widget = shiboken2.wrapInstance(long(ptr), QtWidgets.QMainWindow)
        return widget
pythonファイル
# -*- coding: utf-8 -*-

# OK: parent UI 実現
# OK: single UI 実現

from PySide2 import QtCore, QtGui, QtWidgets
from maya import OpenMayaUI as omUI
from lib import qt  # shiboken2はここで読み込み


class testUI(QtWidgets.QDialog):
    def __init__(self):
        # parent UI
        super(testUI, self).__init__(qt.getMayaWindow())

        self.setWindowTitle('test UI')

        # すでにUIが出来てる場合は削除する #
        # MayaのMainWindowの子Windowを取得
        child_list = self.parent().children()
        for c in child_list:
            # 自分と同じ名前のUIのクラスオブジェクトが存在してたらCloseする
            if self.__class__.__name__ == c.__class__.__name__:
                c.close()
        # ------------------------ #
        btn = QtWidgets.QPushButton("Hello World")
        layout = QtWidgets.QVBoxLayout()

        layout.addWidget(btn)
        self.setLayout(layout)


def main():
    mainWindow = qt.getMayaWindow()
    nowExists = mainWindow.findChildren(testUI)

    # single UI
    # findChildrenで、指定クラスの子を探すのではなく
    # 全ての子オブジェクトのクラス名で判定して、同じなら閉じるようにすれば
    # reloadしようがScriptEditorで実行しようが問題ない。
    for i in nowExists:
        i.close()

    win = testUI()
    win.show()


if __name__ == '__main__':
    print(u'{}.py: loaded as script file'.format(__name__))
    main()
else:
    print(u'{}.py: loaded as module file'.format(__name__))

print(u'モジュール名:{}'.format(__name__))  # 実行したモジュール名を表示する


■パターン2


最終更新日: 2024年4月18日 09:56:45