Skip to content

Instantly share code, notes, and snippets.

@44hero
Last active May 2, 2024 09:44
Show Gist options
  • Save 44hero/f1d9c156f14065e6a6a6453411de0fa6 to your computer and use it in GitHub Desktop.
Save 44hero/f1d9c156f14065e6a6a6453411de0fa6 to your computer and use it in GitHub Desktop.
# 標準ライブラリ #################################################################
from functools import partial
from pprint import pprint
from typing import Tuple, List
# サードパーティライブラリ #########################################################
# from maya import OpenMayaUI, cmds
from PySide2.QtWidgets import (QApplication, QComboBox, QGridLayout,
QMainWindow, QWidget, QHBoxLayout, QVBoxLayout,
QPushButton, QAction, QFrame, QLabel,
QSpacerItem, QSizePolicy,
)
from PySide2.QtGui import QIcon
from PySide2.QtCore import Qt
# ローカルで作成したモジュール ######################################################
# basic_configuration(基本構成)
from .config import SPACE, TITLE, VERSION
# shiboken2 独自モジュール
from ..qt import getMayaWindow # 利用時は、getMayaWindow()
from ..pyside2IniFileSetting import IniFileSetting
# 汎用ライブラリー の使用 #################################################### start
from ...lib.message import message
# from ...lib.message_warning import message_warning
# 汎用ライブラリー の使用 #################################################### end
class Tpl4PySide2_Type1_View(QMainWindow):
u""" < GUIウィンドウを作成するための Viewクラス です >
::
UIを作成するためのメソッドや、UIの更新を行うためのメソッドを実装します。
GUIウィンドウを作成するための PySide2 コードが含まれます。
Viewクラスのコンストラクターは、Modelオブジェクト への参照を受け取ります。
View クラスは GUIウィンドウ を作成し、そのウィンドウ内の要素を更新するためのメソッドを提供します。
.. note::
従来の、
UIのサイズを保存する、
`windowPrefs.mel`
Maya のさまざまな呼び出しに存在する変数を設定および照会できる、プリファレンスの一部である、
maya独自規格{optionVar」
以上2つの Maya専用の 保存参照規格 からの、代替え案として、
PySide2 規格 の .iniファイル
を使用したやり方です。
::
ファイルの保存先には、運用ルールが必要です。。。
ここでは、「マイドキュメント/maya/versionNumber」に
フォルダ「f'{prefix}_{commonName}'」を作り、
設定ファイルが保存されていくようにしています。
ファイル名はクラス変数にして、継承したクラスで変更できるようにします
基本となるUI構成で不可欠となる要素 8つ は以下です
- <UI要素 1>. UIを、Maya window 画面の前面にする
- <UI要素 2>. UIの title設定 と、新規での ポジションとサイズ設定
- <UI要素 3>. UI設定の 保存 と 復元 の機能を 何らかで実現する
- <UI要素 4>. UI設定の 保存 と 復元 の機能
Note): オリジナルメソッド {saveSettings」, 「restore」 で実現
- <UI要素 5>. UIの 重複表示の回避
- <UI要素 6>. UIの 見た目の統一
- <UI要素 7>. -Pyside2特有事項- UI の close 時に delete されるようにする
- <UI要素 8>. UIの window name (objectName) 設定
######
基本となるUI要素は以下の 6つ
- UI-0. 重複しないウインドウ
- UI-1. commonメニュー
- UI-2. メインLayout + common情報 + 追加オプション
- UI-3. ボタンLayout + common底面ボタン3つ
- UI-4. OptionVar を利用したパラメータ管理
- (5. スクリプトベースコマンド入力への対応)
構成要素である以下の1群のみ一部ここ View へ移動
- 1. UI-1. メニュー コマンド群
######
"""
# initialize(初期化関数)コンストラクタです。
# ここで定義されたインスタンス変数は、他のメソッドで上書き・参照が出来ます。
# 当該window を Maya window 画面の前面にする設定 も行っています
def __init__(self, _model, parent = None, flags = Qt.WindowFlags()):
u""" < initialize(初期化関数)コンストラクタ です >
::
ここで定義されたインスタンス変数は、他のメソッドで上書き・参照が出来ます。
基本となるUI構成で不可欠となる要素 8つ の内、以下 2つ を実行しています
- <UI要素 1>. UIを、Maya window 画面の前面にする
- <UI要素 3>. UI設定の保存と復元 の機能を 何らかで実現する
.iniファイルを利用した、
- windowUIの、ポジションとサイズ、
- 他必要箇所となる 入力フィールドの要素、
の、保存と復元 の機能を有効にする
"""
# <UI要素 1>.
# 当該window を Maya window 画面の前面に ######################################## start
if parent is None:
parent = getMayaWindow()
# 当該window を Maya window 画面の前面に ######################################## end
super(Tpl4PySide2_Type1_View, self).__init__(parent, flags)
self.model = _model
self.controller = None
# ######################################################################
self.title = TITLE # <- window の title名
self.space = SPACE
self.version = VERSION
self.underScore = '_'
self.win = TITLE + '_ui' # <- window へ objectName
# 不変要素な、4つ 且つ typeがint であることを明記
self.size: Tuple[int] = (500, 300, 210, 270) # x, y, width, height
self.bgc = "background-color:gray; color: white"
self.infoSummary = (u'XXXのツール\n'
u'の バージョンYYY(ZZZ版) です。')
self.infoDetail = u'AAAのBBBをCCCしました。'
# ######################################################################
# <UI要素 3>.
# コンストラクタのまとまり1_.iniファイル 設定
self.constructorChunk1_iniFileSetting()
# コンストラクタのまとまり2_.iniファイルのパラメーター 設定
self.constructorChunk2_iniFileParam()
...
# コンストラクタのまとまり1_.iniファイル 設定
def constructorChunk1_iniFileSetting(self):
u""" < コンストラクタのまとまり1_.iniファイル 設定 >
######################
"""
# .iniファイルの設定 ########################################################### start
self.iniFS = IniFileSetting(self.title) # pyside2IniFileSetting モジュール
filename, _settings = self.iniFS.iniFileSetting() # .iniファイルの設定 メソッド
self.filename = filename
self._settings = _settings
# .iniファイルの設定 ########################################################### end
# コンストラクタのまとまり2_.iniファイルのパラメーター 設定
def constructorChunk2_iniFileParam(self):
u""" < コンストラクタのまとまり2_.iniファイルのパラメーター 設定 >
######################
"""
# .iniファイルのパラメーター設定 ##################################### start
self.iniFileParam = {'geo_iFP': 'geometry',
}
# self.od = OrderedDict(self.iniFileParam) # 順序付き辞書 定義
# .iniファイルのパラメーター設定 ##################################### end
# オリジナルメソッド
# 重複ウィンドウの回避関数
def _duplicateWindowAvoidFunction(self, winName: str):
u""" < 重複ウィンドウの回避関数 です >
オリジナルメソッド
:param str winName: self.win # window ui name に相当します
"""
widgets = QApplication.allWidgets()
for w in widgets:
if w.objectName() == winName:
# w.close()
w.deleteLater()
# オリジナルメソッド
# Window基本設定
def _windowBasicSettings(self):
u""" < 当該window の、基本設定 をいっぺんに行う 関数 です >
オリジナルメソッド
.. note::
- set window title と 新規のポジションとサイズ設定 : <UI要素 2>.
- set window name : <UI要素 8>.
はここで行っています
基本となるUI構成で不可欠となる要素 8つ の内、以下 5つ を実行しています
- <UI要素 2>. UIの title設定 と、新規での ポジションとサイズ設定
- <UI要素 5>. UIの重複の回避
- <UI要素 6>. UIの見た目の統一
- <UI要素 7>. -Pyside2特有事項- UIのclose時にdeleteされるようにする
- <UI要素 8>. UI window name (objectName) 設定
"""
# <UI要素 2>.
# UI設定の保存と復元 の機能 ###################################################### start
# self.setWindowTitle(self.title[2:] + self.space + self.version) # <- window の title名 設定
self.setWindowTitle(self.title + self.space + self.version) # <- window の title名 設定
# ウィンドウが一度でも作成されているかどうかを確認
# 純粋に初めてのUI作成時: False # 以下を実行
# 次回再度ロード時は: True # ここをスキップし、前回の ポジションとサイズ が復元される
if not self.isVisible():
self.setGeometry(*self.size) # 完全に新規にUI作成したときの初期値。アンパック(*)は重要
# UI設定の保存と復元 の機能 ###################################################### end
# <UI要素 5>.
# UIの 重複表示の回避 ########################################################### start
# old style ############################### start
# child_list = self.parent().children()
# for c in child_list:
# # 自分と同じ名前のUIのクラスオブジェクトが存在してたらCloseする
# if self.__class__.__name__ == c.__class__.__name__:
# c.close()
# old style ############################### end
self._duplicateWindowAvoidFunction(winName = self.win) # 重複ウィンドウの回避関数
# UIの 重複表示の回避 ########################################################### end
# <UI要素 6>.
# UIの 見た目の統一 ############################################################# start
# Windows用 window の見た目の制御を行います
# # type1
# # minimize, maximize, close 有り
# self.setWindowFlags(Qt.Window)
# # type2
# # minimize のみ有り
# self.setWindowFlags(Qt.Window | Qt.WindowMinimizeButtonHint)
# type3
# close のみ有り
self.setWindowFlags(Qt.Window | Qt.WindowCloseButtonHint) # windowの右上にx印(close)のみ
# UIの 見た目の統一 ############################################################# end
# self.setUpdatesEnabled(True) # デフォルトでTrueです
# <UI要素 7>.
# -Pyside2特有事項- UI の close 時に delete されるようにする ###################### start
# PySideで作ったGUIは何もしてないと close しても delete はされません。
# windowオブジェクト に `setAttribute` することで close 時に delete されるようになります。
self.setAttribute(Qt.WA_DeleteOnClose) # <- close 時に delete 設定
# -Pyside2特有事項- UI の close 時に delete されるようにする ###################### end
# <UI要素 8>.
# UIの window name (objectName) 設定 ########################################## start
# set window name
self.setObjectName(self.win) # <- window へobjectName 設定
# UIの window name (objectName) 設定 ########################################## end
# <UI要素 4>.
# UI設定の保存と復元 の機能 の 一部 ############################################### start
# different style ######################## start
# Note: .iniファイルを使用せず、maya独自規格使用時 有効です
# 但し、UIに入力フィールドとう存在した場合には、それらはここには含まれず、他のアプローチも必要
# window を close したときのサイズ・位置のみが `windowPrefs.mel` に保存されるようになり、
# 次回 show 時に復元されるようになります。
# self.setProperty("saveWindowPref", True)
# different style ######################## end
# UI設定の保存と復元 の機能 の 一部 ############################################### end
# UIの起動 関数
def createUI(self):
u""" < UIの起動 関数 です >
"""
self._windowBasicSettings() # 当該window の設定をいっぺんに行う 関数
self.controller = self.model.controller # 和えて明示しています。無くてもこのケースでは実行可。
# print('--- createUI, koko')
# print(self.ui)
#
# if self.ui is not None:
# self.ui.deleteLater()
# 1):###############################################################################
# 概要: メインウィンドウ の中央に配置される セントラルウィジェット です
# 1): QWidget -Widget- ############################################## -Widget- start
self.central_wid = QWidget(self) # セントラルウィジェット
self.setCentralWidget(self.central_wid) # 中央に配置
# 1): QWidget -Widget- ############################################## -Widget- end
# 1):###############################################################################
# Clear existing menu items
# self.menuBar().clear()
# UI-1. commonメニュー
self.commonMenu() # ############################### UI-1. commonメニュー
# 2):###############################################################################
# 概要: セントラルウィジェット 内の メインレイアウト です
# 2): QVBoxLayout -Layout- ########################################## -Layout- start
# セントラルウィジェット に 縦のメインレイアウト
# を作成し そのウィジェット へ set ############### 作成しただけでは表示されません -Layout-
main_vbxLay = QVBoxLayout(self.central_wid) # メインレイアウト
# レイアウトの余白を調整
main_vbxLay.setContentsMargins(3, 3, 3, 3)
# 2): QVBoxLayout -Layout- ########################################## -Layout- end
# 2):###############################################################################
# 3):###############################################################################
# 概要: メインレイアウト 内には、大フレーム群 と 底面ボタン群 が縦に配置されます
# 3.1): 大フレーム群 -Widget- ######################################### -Widget- start
# セントラルウィジェット 内に ウィジェット(大フレーム用)
# を作成 ###################################### 作成しただけでは表示されません -Widget-
self.frame_frWid = QFrame(self.central_wid) # フレームウィジェット(大フレーム用)
# フレームウィジェット(大フレーム用) に 縦のレイアウト(大フレーム用)
# を作成し そのウィジェット へ set ############### 作成しただけでは表示されません -Layout-
self.frame_vbxLay = QVBoxLayout(self.frame_frWid) # レイアウト(大フレーム用)
# フレームウィジェット(大フレーム用) を メインレイアウト
# に追加 ###################################### 追加して初めて表示されます -表示-
main_vbxLay.addWidget(self.frame_frWid)
# フレームウィジェット(大フレーム用) を装飾
# 設定を施す ###################################
self.frame_frWid.setFrameShape(QFrame.StyledPanel) # 枠のスタイルを設定
# まとまりA
# 大フレーム群 に収まっているものです ######################################## start
# UI-2. common情報
# 設定を施す ###################################
self.commonInformation(frame_layout = self.frame_vbxLay) # ############################ UI-2. common情報
# UI-2. 追加オプションのまとまり
# 設定を施す ###################################
self.displayOptions(frame_layout = self.frame_vbxLay) # #################### UI-2. 追加オプションのまとまり
# 大フレーム群 に収まっているものです ######################################## end
# 常に、大フレーム のトップ に順番に配置されるようにするため、垂直スペーサーを追加して間隔を制御
# まとまりA を装飾
# 設定を施す ###################################
spacer = QSpacerItem(20, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.frame_vbxLay.addItem(spacer)
# 3.1): 大フレーム群 -Widget- ######################################### -Widget- end
# 3.2): 底面ボタン群 -Layout- ###################################$##### -Layout- start
# セントラルウィジェット 内に 水平レイアウト(底面ボタン用)
# を 直接 作成 追加 ###################################### 一遍に行えます
self.button_hbxLay = QHBoxLayout(self.central_wid) # レイアウト(底面ボタン用)
# まとまりB
# 底面ボタン群 です ####################################################### start
# UI-3. common底面ボタン3つ
# 設定を施す ###################################
self.commonButtons(self.button_hbxLay) # ######################## UI-3. common底面ボタン3つ
# 底面ボタン群 です ####################################################### end
# レイアウト(底面ボタン用) を メインレイアウト
# に追加 ###################################### 追加して初めて表示されます -表示-
main_vbxLay.addLayout(self.button_hbxLay)
# 3.2): 底面ボタン群 -Layout- ###################################$##### -Layout- end
# 3):###############################################################################
self.show() # 最終的にUIを作成
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment