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") self.UserOrNot() self.window.show() def UserOrNot(self): self.layout = QGridLayout() self.UserQuestion = QLabel("Are you an existing user or a new user?") self.layout.addWidget(self.UserQuestion) ## creates a button for existing users self.ExistingUser = QPushButton("Existing user") self.layout.addWidget(self.ExistingUser) ## creates a button for new users self.NewUser = QPushButton("New user") self.NewUser.clicked.connect(NewUserPressed) self.layout.addWidget(self.NewUser) self.window.setLayout(self.layout) # self.window.show() 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") self.CreateUserForm() 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.layout.addWidget(self.OKButton) self.CancelButton = QPushButton("Cancel") self.layout.addWidget(self.CancelButton) self.window.setLayout(self.layout) self.window.show() if __name__ == '__main__': import sys app = QApplication(sys.argv) main = StartScreen() sys.exit(app.exec_())
-
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 haveself
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:
self.NewUser.clicked.connect(self.NewUserPressed)
Then you need to accept the parent to your new instance and pass it to the base class init.
Now when you subclass fromQWidget
which is what you do withclass 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") self.UserOrNot() self.show()
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 aQDialog
!class CreateUser(QDialog): def __init__(self, parent): super(CreateUser, self).__init__(parent)
This can also be
Esc
-aped away nicely. And has Signals likeaccepted
andrejected
👍Now
self.layout
is a member function ofQWidget
! So If you doself.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 inself
you can even skip thesetLayout()
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:
... self.setup_ui() self.show() def setup_ui(self): ... self.new_user = QPushButton("New user") self.new_user.clicked.connect(self.new_user_pressed) layout.addWidget(self.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.
cheers:
eRiC