Qtで複数windowを扱うtemplete

mayaでツールを作成するときに始めに表示されるUIから別のwindowを表示する方法を記録します

[こちら](https://www.pythonguis.com/tutorials/pyside-creating-multiple-windows/)のサイトが大変参考になりました

普段わたくしが使用しているwindowのtempleteがこちら
```python
from maya import OpenMayaUI, cmds
from PySide2 import QtWidgets, QtCore
import shiboken2

class MainUI(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(MainUI, self).__init__(parent)

        self.setWindowTitle('windowTitle')
        self.resize(100, 100)

def main():
    mayaWindow = shiboken2.wrapInstance(
        int(OpenMayaUI.MQtUtil.mainWindow()), QtWidgets.QWidget)

    existsWindow = mayaWindow.findChildren(QtWidgets.QWidget, 'WindowName')
    for w in existsWindow:
        w.close()

    ui = MainUI(mayaWindow)
    ui.setObjectName('WindowName')
    ui.setWindowFlags(QtCore.Qt.Window|QtCore.Qt.WindowCloseButtonHint)
    ui.show()
```
![2025-01-07_15h12_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125058/f08002f0-0321-deb5-8698-f00dc6de7692.png)

まずは二つ目のwindowのクラスを作成します
```python
class SecondUI(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(SecondUI, self).__init__(parent)

        self.setWindowTitle('secondWindow')
        self.resize(150,100)

        layout = QtWidgets.QVBoxLayout(self)
        label = QtWidgets.QLabel('secondWindow')

        layout.addWidget(label)
```
一つ目のwindowに二つ目を表示するボタンと関数を追加します
```python
class MainUI(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(MainUI, self).__init__(parent)

        self.setWindowTitle('firstWindow')
        self.resize(100, 100)

        layout = QtWidgets.QVBoxLayout(self)
        btn_second = QtWidgets.QPushButton('showSecondWindow')
        btn_close = QtWidgets.QPushButton('close')

        layout.addWidget(btn_second)
        layout.addWidget(btn_close)

        btn_second.clicked.connect(self.showSecond)
        btn_close.clicked.connect(self.close)

    def showSecond(self):
        mayaWindow = shiboken2.wrapInstance(
            int(OpenMayaUI.MQtUtil.mainWindow()), QtWidgets.QWidget)
        existsWindow = mayaWindow.findChildren(QtWidgets.QWidget,'secondWindow')
        for w in existsWindow:
            w.close()

        self.second_ui = SecondUI(self)
        self.second_ui.setObjectName('secondWindow')
        self.second_ui.setWindowFlags(
            QtCore.Qt.Window|QtCore.Qt.WindowCloseButtonHint)
        self.second_ui.show()
```
showSecond関数の中でself.second_uiという方とにしているのは、上記の参考にしたサイトに書かれていたものです
ローカル変数のままだとボタンを押した直後しか二番目のwindowが表示されないので、どこかのオブジェクト(ここでは一番目のwindow)に格納するとのことでした
second_uiとしてローカル関数にしてもなぜか表示されるのですが、たまたまの可能性が高いのでここではself.second_uiとします

![2025-01-07_17h31_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125058/d8a01a85-7c08-f88f-d045-23a940f8e1e7.png)
実行すると二番目のwindowが表示できるようになります
ここで、一番目のwindowをcloseした場合に二番目のwindowもcloseしたいとなりました
そこで一番目のwindowのcloseEventに二番目のwindowのclose処理を追加します
```python
def closeEvent(self,event):
    try:
        self.second_ui.close()
    except:
        pass
    QtWidgets.QWidget.closeEvent(self,event)
```
この処理を追加するにはsecond_uiはローカル変数では都合が悪いですね

以下が上記の処理を全て追記したものになります
```python
from maya import OpenMayaUI, cmds
from PySide2 import QtWidgets, QtCore
import shiboken2

class MainUI(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(MainUI, self).__init__(parent)

        self.setWindowTitle('firstWindow')
        self.resize(100, 100)

        layout = QtWidgets.QVBoxLayout(self)
        btn_second = QtWidgets.QPushButton('showSecondWindow')
        btn_close = QtWidgets.QPushButton('close')

        layout.addWidget(btn_second)
        layout.addWidget(btn_close)

        btn_second.clicked.connect(self.showSecond)
        btn_close.clicked.connect(self.close)

    def showSecond(self):
        mayaWindow = shiboken2.wrapInstance(
            int(OpenMayaUI.MQtUtil.mainWindow()), QtWidgets.QWidget)
        existsWindow = mayaWindow.findChildren(QtWidgets.QWidget,'secondWindow')
        for w in existsWindow:
            w.close()

        self.second_ui = SecondUI(self)
        self.second_ui.setObjectName('secondWindow')
        self.second_ui.setWindowFlags(
            QtCore.Qt.Window|QtCore.Qt.WindowCloseButtonHint)
        self.second_ui.show()

    def closeEvent(self,event):
        try:
            self.second_ui.close()
        except:
            pass
        QtWidgets.QWidget.closeEvent(self,event)

class SecondUI(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(SecondUI, self).__init__(parent)

        self.setWindowTitle('secondWindow')
        self.resize(150,100)

        layout = QtWidgets.QVBoxLayout(self)
        label = QtWidgets.QLabel('secondWindow')

        layout.addWidget(label)

        btn_close.clicked.connect(self.close)

def main():
    mayaWindow = shiboken2.wrapInstance(
        int(OpenMayaUI.MQtUtil.mainWindow()), QtWidgets.QWidget)

    existsWindow = mayaWindow.findChildren(QtWidgets.QWidget, 'doubleWindow')
    for w in existsWindow:
        w.close()

    ui = MainUI(mayaWindow)
    ui.setObjectName('doubleWindow')
    ui.setWindowFlags(QtCore.Qt.Window|QtCore.Qt.WindowCloseButtonHint)
    ui.show()
```

同僚のプログラマに聞いたところ、二番目のwindowの処理はもっとプログラム的に行儀のいいやりかたがあるらしいです
とりあえず動作しますが、なにか助言がありましたら是非お願いします