元ネタ:
PyQtを使って実用的なアプリを作ろうとすると、描画や設定などの画面を個別に表示するために複数ウィンドウを実装したいことがあります。
まず、素直に以下のようなコードを実装・実行してみます。
import sys from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QPushButton, QLabel, QVBoxLayout, ) class AnotherWindow(QWidget): def __init__(self): super().__init__() layout = QVBoxLayout() self.label = QLabel("Another Window") layout.addWidget(self.label) self.setLayout(layout) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.button = QPushButton("Push for Window") self.button.clicked.connect(self.show_new_window) self.setCentralWidget(self.button) def show_new_window(self, checked): w = AnotherWindow() w.show() app = QApplication(sys.argv) w = MainWindow() w.show() app.exec()
AnotherWindow
が2つ目の画面です。
このコードを実行しても、以下のGIFのように2つ目の画面AnotherWindow
はすぐに消えてしまいます。
解決策として、PyQtでは新規Widget
を、親となるWidget
やMainWindow
のメンバ変数とする必要があります。
具体的には、上記のコードではshow_new_window()
を以下のように変更すればOKです。
def show_new_window(self, checked): self.w = AnotherWindow() self.w.show()
実行すると、以下のように2つのウィンドウが表示されました。
3つ以上の場合も同様であり、3つの場合の例を以下に示します。
import sys from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QPushButton, QLabel, QVBoxLayout, ) class AnotherWindow2(QWidget): def __init__(self): super().__init__() layout = QVBoxLayout() self.label = QLabel("Another Window") layout.addWidget(self.label) self.setLayout(layout) class AnotherWindow(QWidget): def __init__(self): super().__init__() layout = QVBoxLayout() self.button = QPushButton("Push AnotherWindow") self.button.clicked.connect(self.show_new_window) layout.addWidget(self.button) self.setLayout(layout) def show_new_window(self, checked): self.w = AnotherWindow2() self.w.show() class MainWindow(QMainWindow): def __init__(self): super().__init__() self.button = QPushButton("Push MainWindow") self.button.clicked.connect(self.show_new_window) self.setCentralWidget(self.button) def show_new_window(self, checked): self.w = AnotherWindow() self.w.show() app = QApplication(sys.argv) w = MainWindow() w.show() app.exec()
実行例: