Important: Please read the Qt Code of Conduct -

Pyqt5 code not working

  • so I'm new to PyQt5 and have am trying to open a new window when a button is pressed. I know this should be simple and have managed to copy other examples to produce my code but it doesn't run - the second window opens then instantly closes. this should be a simple fix but I don't get where I've gone wrong, could anyone help me? thanks

    class StartScreen(QWidget):
        def __init__(self):
            self.window = QWidget()
            self.window.setGeometry(50, 50, 350, 200)
            self.window.setWindowTitle("Fantasy F1")
        def UserOrNot(self):
            self.layout = QGridLayout()
            self.UserQuestion = QLabel("Are you an existing user or a new user?")
            ## creates a button for existing users
            self.ExistingUser = QPushButton("Existing user")
            ## creates a button for new users
            self.NewUser = QPushButton("New user")
    def NewUserPressed():
        print("button pressed")
        main = CreateUser()        
    class CreateUser(QWidget):
        def __init__(self):
            self.window = QWidget()
            self.window.setGeometry(50, 50, 350, 250)
            self.window.setWindowTitle("Create a team")
        def CreateUserForm(self):
            self.layout = QFormLayout()
            ## creates a form (age is spinbox to make sure user can only enter numbers)
            self.layout.addRow(QLabel("*Username:"), QLineEdit())
            self.layout.addRow(QLabel("*Team name:"), QLineEdit())
            self.layout.addRow(QLabel("*First name:"), QLineEdit())
            self.layout.addRow(QLabel("*Last name:"), QLineEdit())
            self.layout.addRow(QLabel("*Password:"), QLineEdit())
            self.layout.addRow(QLabel("Email address:"), QLineEdit())
            self.layout.addRow(QLabel("Age:"), QSpinBox())
            self.layout.addRow(QLabel("Those with a * must be filled in."))
            self.OKButton = QPushButton("OK")
            self.CancelButton = QPushButton("Cancel")
    if __name__ == '__main__':
        import sys
        app = QApplication(sys.argv)
        main = StartScreen()

  • Hi welcome! Pyqt5? This is PySide2/Qt for Python! :D
    but well the code should work anyway:

    First off: When you want a child window you need to pass the parent somehow. I'd make the NewUserPressed a member function of the main window so you have self at hand and then pass the according object to it:

    def NewUserPressed(self):
        print("button pressed")
        main = CreateUser(self.window)

    of course you also need to call this like this now:


    Then you need to accept the parent to your new instance and pass it to the base class init.
    Now when you subclass from QWidget which is what you do with class CreateUser(QWidget) ...: you need to call the init function of the base class as well! Easy:

    class CreateUser(QWidget):
        def __init__(self, parent):
        super(CreateUser, self).__init__(parent)

  • While this ^ would make your code working already I'd still point to some other issues:

    You start off with QWidget instance already and put another one right in there? Without transforming it? That can be shortened with initializing your base class in the beginning too:

    class StartScreen(QWidget):
        def __init__(self):
            super(StartScreen, self).__init__()
            self.setGeometry(50, 50, 350, 200)
            self.setWindowTitle("Fantasy F1")

    Same goes for the subwindow! But as its a QWidget too Qt will try to embedd it into the current windows composition right away. I'd make it a QDialog!

    class CreateUser(QDialog):
        def __init__(self, parent):
            super(CreateUser, self).__init__(parent)

    This can also be Esc-aped away nicely. And has Signals like accepted and rejected 👍

    Now self.layout is a member function of QWidget! So If you do self.layout = QGridLayout() you override the function with a variable pointing to the layout instance. Of course we're in Python and everything can be monkeypatched and overridden this is fine. But better practice is to keep these intact when there is no need to override. And if you just add to the in the layout in this one function you don't even need to make it a member variable:

    def CreateUserForm(self):
        layout = QFormLayout(self)

    You can still access the layout later via self.layout() because you did not override :)
    When you pass in self you can even skip the setLayout() later on!

    ... well this is nitpicking but ... 🤷‍♂️

    make use of DRY principle:

        for item in ['*Username', '*Team name', '*First name',
                     '*Last name', '*Password', 'Email address']:
            layout.addRow(QLabel(item + ':'), QLineEdit())

    get familiar with pep8 and make variables and functions lower case:

    def setup_ui(self):
        self.new_user = QPushButton("New user")
    def new_user_pressed(self):

    in general: try to make your code snippet as short as possible cooking it down to the very part thats not working.

  • @ewerybody thank you so much! apologies for the late reply, I didn't get the notifications. I'll make those changes and see how it works, thank you so much, I would never have been able to make those changes myself

Log in to reply