Home > Enterprise >  Pyqt5 - how to go back to hided Main Window from Secondary Window?
Pyqt5 - how to go back to hided Main Window from Secondary Window?

Time:10-04

If I click Back from the second window, the program will just exit. How do I go back to mainwindow in this case? I assume I will need some more code in that clickMethodBack function.

import os
import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QLabel, QPushButton
import time
from PyQt5.QtCore import QSize

class GUI_Window():
 
    def __init__(self):
        self.main_window()
        return

    def main_window(self):
        app = PyQt5.QtWidgets.QApplication(sys.argv)
        self.MainWindow = MainWindow_()                                                  
        self.MainWindow.show()                                                                    
        app.exec_()                                                                      
        return
                  

class MainWindow_(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)

        self.TestAButton = QPushButton("TestA", self)
        self.TestAButton.clicked.connect(self.TestA_clickMethod)
        self.TestAButton.move(20, 0)

        self.CloseButton = QPushButton("Close", self)
        self.CloseButton.clicked.connect(self.Close_clickMethod)
        self.CloseButton.move(20, 40)

        self.TestingA = TestA_MainWindow()     
    def TestA_clickMethod(self):
        self.TestAButton.setEnabled(False)
        time.sleep(0.2)
        self.TestingA.show()
        self.hide()   

        try:
            if self.TestingA.back == True:
                self.show()
        except:
            None

    def Close_clickMethod(self):
        self.Test_Choice = 'Exit'
        self.close()


class TestA_MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(QSize(980,700))
        self.setWindowTitle("TestA")

        self.Back_Button = False

        self.closeButton = QPushButton("Close", self)
        self.closeButton.clicked.connect(self.clickMethodClose)

        self.returnButton = QPushButton("Back", self)
        self.returnButton.clicked.connect(self.clickMethodBack)
        self.returnButton.move(0,30)

    def clickMethodClose(self):
        self.Back_Button = False
        self.close()

    def clickMethodBack(self):
        self.returnButton.setEnabled(False)
        time.sleep(0.5)
        self.back = True
        self.close()






# Run if Script
if __name__ == "__main__":
    main = GUI_Window()                                                   # Initialize GUI

CodePudding user response:

Your code has two very important issues.

  1. you're using a blocking function, time.sleep; Qt, as almost any UI toolkit, is event driven, which means that it has to be able to constantly receive and handle events (coming from the system or after user interaction): when something blocks the event queue, it completely freezes the whole program until that block releases control;
  2. you're checking for the variable too soon: even assuming the sleep would work, you cannot know if the window is closed after that sleep timer has ended;

The solution is to use signals and slots. Since you need to know when the second window has been closed using the "back" button, create a custom signal for the second window that will be emitted whenever the function that is called by the button is closed.

from PyQt5 import QtCore, QtWidgets

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        central = QtWidgets.QWidget()
        layout = QtWidgets.QHBoxLayout(central)
        self.testButton = QtWidgets.QPushButton('Test A')
        self.closeButton = QtWidgets.QPushButton('Close')
        layout.addWidget(self.testButton)
        layout.addWidget(self.closeButton)
        self.setCentralWidget(central)

        self.testButton.clicked.connect(self.launchWindow)
        self.closeButton.clicked.connect(self.close)

    def launchWindow(self):
        self.test = TestA_MainWindow()
        self.test.backSignal.connect(self.show)
        self.hide()
        self.test.show()

class TestA_MainWindow(QtWidgets.QWidget):
    backSignal = QtCore.pyqtSignal()
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QHBoxLayout(self)
        self.closeButton = QtWidgets.QPushButton('Close')
        self.backButton = QtWidgets.QPushButton('Back')
        layout.addWidget(self.closeButton)
        layout.addWidget(self.backButton)

        self.closeButton.clicked.connect(self.close)
        self.backButton.clicked.connect(self.goBack)

    def goBack(self):
        self.close()
        self.backSignal.emit()


def GUI_Window():
    import sys
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    GUI_Window()

Notes:

  • I removed the GUI_Window class and made a function, as using a class for that is not really useful;
  • you should always prefer layout managers instead of setting manual geometries;
  • widgets should not be added to a QMainWindow as direct children, and a central widget should always be used (see the creation and use of central in the example); read more about it in the documentation;
  • only classes and constants should be capitalized, while variables, attributes and functions should always have names starting with a lowercase letter;
  • Related