Confirm login dialog and show main windows pyqt5
-
@JonB
It's a pushButton click inside the dialog form(class)self.btnReg.clicked.connect(self.register)@behruz-montazeri
But it's the dialog fromself.dialog.exec_()that you want the button to exit, right? So then clearly it would beself.dialog.accept()?Usually you write handlers (slots) for a dialog in the dialog class's code (by sub-classing the dialog), not in the caller's code. I get mixed up the way you have done it. Your dialog widgets like
lineEditUser&lineEditPassare members ofselfbutselfis not the dialog they appear on but rather the form which opens the dialog, is that right? Confusing! -
@behruz-montazeri
But it's the dialog fromself.dialog.exec_()that you want the button to exit, right? So then clearly it would beself.dialog.accept()?Usually you write handlers (slots) for a dialog in the dialog class's code (by sub-classing the dialog), not in the caller's code. I get mixed up the way you have done it. Your dialog widgets like
lineEditUser&lineEditPassare members ofselfbutselfis not the dialog they appear on but rather the form which opens the dialog, is that right? Confusing!@JonB
i guess it better to be dialog.exec_() instead of self.dialog.exec_(). The actual dialog has two button exit button and register button. -
@JonB
i guess it better to be dialog.exec_() instead of self.dialog.exec_(). The actual dialog has two button exit button and register button.@behruz-montazeri
This is main window:class Ui_MainWindow(object): def setupUi(self, MainWindow): self.loginForm() def loginForm(self): dialog = QDialog() dialog.ui = Ui_UsrDialog() dialog.ui.setupUi(dialog) dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose) if ( not dialog.exec() ): sys.exit(0) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())This is dialog form:
class Ui_UsrDialog(QtWidgets.QDialog): def __init__(self): super(Ui_UsrDialog, self).__init__() self.setupUi(self) def setupUi(self, Dialog): self.btnReg.clicked.connect(self.register) def register(self): if self.lineEditUser.text() == "1" and self.lineEditPass.text()== "1": self.accept() # not work also self.reject() -
@behruz-montazeri
This is main window:class Ui_MainWindow(object): def setupUi(self, MainWindow): self.loginForm() def loginForm(self): dialog = QDialog() dialog.ui = Ui_UsrDialog() dialog.ui.setupUi(dialog) dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose) if ( not dialog.exec() ): sys.exit(0) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())This is dialog form:
class Ui_UsrDialog(QtWidgets.QDialog): def __init__(self): super(Ui_UsrDialog, self).__init__() self.setupUi(self) def setupUi(self, Dialog): self.btnReg.clicked.connect(self.register) def register(self): if self.lineEditUser.text() == "1" and self.lineEditPass.text()== "1": self.accept() # not work also self.reject()@behruz-montazeri
OK. Look, you originally said:Dialog form button click function called register :
But I do not see anywhere that does actually call your
register(). Put in debug statement likeprint()to prove when it calls yourregister().I see only that
btnExitcallsself.closeFrm(), and I do not see that function defined either.I can only tell you: if the outside world calls
QDialog.exec(), then that will return, withTrue, if your button'sclickedcallsaccept(). -
@behruz-montazeri
OK. Look, you originally said:Dialog form button click function called register :
But I do not see anywhere that does actually call your
register(). Put in debug statement likeprint()to prove when it calls yourregister().I see only that
btnExitcallsself.closeFrm(), and I do not see that function defined either.I can only tell you: if the outside world calls
QDialog.exec(), then that will return, withTrue, if your button'sclickedcallsaccept().@JonB
I missed to write the call of register function. I edited the post. Yes print statement print when i click and when the condition meet. -
@behruz-montazeri
OK. Look, you originally said:Dialog form button click function called register :
But I do not see anywhere that does actually call your
register(). Put in debug statement likeprint()to prove when it calls yourregister().I see only that
btnExitcallsself.closeFrm(), and I do not see that function defined either.I can only tell you: if the outside world calls
QDialog.exec(), then that will return, withTrue, if your button'sclickedcallsaccept().This post is deleted! -
@behruz-montazeri
OK. Look, you originally said:Dialog form button click function called register :
But I do not see anywhere that does actually call your
register(). Put in debug statement likeprint()to prove when it calls yourregister().I see only that
btnExitcallsself.closeFrm(), and I do not see that function defined either.I can only tell you: if the outside world calls
QDialog.exec(), then that will return, withTrue, if your button'sclickedcallsaccept().@JonB
Eventually i get it working by :self.btnReg.clicked.connect(lambda: self.register(Dialog))And :
def register(self,Dialog): if self.lineEditUser.text() == "1" and self.lineEditPass.text()== "1": print("clicked") Dialog.accept() -
@JonB
Eventually i get it working by :self.btnReg.clicked.connect(lambda: self.register(Dialog))And :
def register(self,Dialog): if self.lineEditUser.text() == "1" and self.lineEditPass.text()== "1": print("clicked") Dialog.accept()@behruz-montazeri
Yes, because finally you are callingaccept()on the dialog instance!I think you are learning Qt & PyQt. Even though what you have now works, I think you should consider rewriting a bit, so that going forward your coding style will be better.
One small point is: don't name your variables starting with an upper-case letter, only do that for your classes. So your
Dialogparameter should be speltdialoginstead.A bigger point is what I said about where you define your methods and what
selfis. You have keptselfbeing your form, even when you are in code which is executing in the dialog. And you have member variables likeself.lineEditUser&self.lineEditPasswhich are for widgets on the dialog, even thoughselfis the form. This is not good for anybody.A much better pattern is to sub-class your dialog instance from
QDialog, and put the dialog's variables & methods in that sub-class, not in your form code which calls the dialog. (Oh, I see you have begun to do that, but not fully completed.) It will make your code much easier to understand & maintain in the long run. Your code should be written more like the following:class MyDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.btnReg.clicked.connect(self.register) def register(self): if self.lineEditUser.text() == "1" and self.lineEditPass.text()== "1": self.accept() def loginForm(self): self.dialog = MyDialog(self) ... if self.dialog.exec(): ....This assumes that
btnReg,lineEditUser&lineEditPassare all on the dialog. Note how we define theregister()method as a member of the dialog, not of the form, and duringregister()theselfrefers to the dialog itself, not the form. That's where it belongs. -
@Denni-0 said in Confirm login dialog and show main windows pyqt5:
For this very reason within my code I capitalize most of my variable/methods/classes some of which will get a type prefix in lower case
.
Now were I writing code to be consumed by the general public then I would conform more to this standard put forth by @JonB but when I am not I use my standard. This is where Style is something that is what you choose versus Standards which are wiredWell, you have had your say and you have your opinion, which is fair enough. But Python (as well as C++) convention on this is clear enough (e.g. https://www.python.org/dev/peps/pep-0008). Now, in Python one is supposed to use underscores (snake_case) rather than camel-case, but there are plenty of examples out there of people using camelCase, and in the case of PyQt there is good reason to accept that in order to be consistent with the whole of the Qt libraries you are using which universally adopts the camelCase on variables/functions while using Upper Camel Case on types, and is precisely what the author of PyQt chose when implementing.
IMHO encouraging people to use "personal styles" when coding "not for public" is not good. I mean it politely, and doubtless we will agree to differ. I don't think anyone else on this forum would suggest "personal styling" like this, So at least the OP has a choice.
-
@Denni-0 said in Confirm login dialog and show main windows pyqt5:
@pyqtSlot() def Register(self): if self.lneUserName.text() == "1" and self.lneUserPass.text()== "1": self.Parent.UsrRegd = True self.close()I would advise the OP absolutely not to do it this way. This was the whole point of learning to use
QDialog.accept()etc. Doing stuff viaself.Parent.UsrRegd = Truewhere you write into
self.Parentis wrong for so many reasons (not the least of which is that it may well crash). Again, if you don't agree, I'll leave it to others here to debate the case, but this is an anti-pattern beginners should not be using..... This one matters. -
@Denni-0
Briefly.And I would challenge you to back up your fictitious statement with some actual hard facts on how this is going to make your program crash or adversely affect it in anyway
I was polite to you, it's not a "fictitious" statement. The default constructor for
QDialogisQDialog(parent=None). That will mean yourUserLoginwill haveself.Parent is Nonewhen invoked asdialog = UserLogin(). And then yourself.Parent.UsrRegd = Truewill "crash" (or at least throw an exception from Python, which is all I meant).Writing code which has one object read/write into another object when there is absolutely no need to do so breaks the principles of OO. The code only works if a parent is passed in and the parent has a member variable named
UsrRegdfor the result. Fortunately, only Python lets you do that, it would not compile from C++. Making one object's code only work when called in a certain fashion from the outside world is not good, and it's not a good example to set for beginners. There are times when a "child" does need to access its parent, but this is not one of them.Meanwhile, Qt has perfectly good, documented, intended mechanism that
QDialog::exec()returns true/false to the caller according as it invokesQDialog.accept()/reject(). From https://doc.qt.io/qt-5/qdialog.html#details:The most common way to display a modal dialog is to call its
exec()function. When the user closes the dialog,exec()will provide a useful return value. Typically, to get the dialog to close and return the appropriate value, we connect a default button, e.g. OK, to theaccept()slot and a Cancel button to thereject()slot. Alternatively you can call thedone()slot withAcceptedorRejected.and
Return Value (Modal Dialogs)
Modal dialogs are often used in situations where a return value is required, e.g. to indicate whether the user pressed OK or Cancel. A dialog can be closed by calling the
accept()or thereject()slots, andexec()will return Accepted or Rejected as appropriate. Theexec()call returns the result of the dialog.That is what all examples will use. If any other experts here would care to comment, or if you asked this on, say, stackoverflow, I think you would find you got the same response. Whether that would convince you I do not know.
-
Hi,
To add to @JonB, this
self.Parent.UsrRegd = Truehas a name: tight coupling.
This is the open door to maintenance hell. Having a child manipulate the internals of its parent is usually sign of architecture problems.
There's signals and slots for interaction or setters/getters but the child shall never care about the class that is using it, it is not its role. -
Setting directly a variable value in a parent class is not a callback.
Also, callbacks are provided to classes that ignores completely how the class that is setting said callback works. Which again avoids tight coupling which is the point currently debated.
-
@Denni-0 said in Confirm login dialog and show main windows pyqt5:
Now were I writing code to be consumed by the general public then I would conform more to this standard put forth by @JonB but when I am not I use my standard.
Mmm, it seems not a well thought decision.
What if something you wrote "internally" has now the opportunity "to be consumed by the general public"?
Are you going to jump and re-write such code?
I cannot stand but think about "there's no second chance for first impressions"self.Parent.UsrRegd = TrueAs several people already mentioned, tight coupling and not a good approach detectors are firing up here.
What if you have written a modular dialog you intend to reuse in several parts of your application? You're imposing that the parent class have such property.
Again, it doesn't seem smart. -
@behruz-montazeri
Yes, because finally you are callingaccept()on the dialog instance!I think you are learning Qt & PyQt. Even though what you have now works, I think you should consider rewriting a bit, so that going forward your coding style will be better.
One small point is: don't name your variables starting with an upper-case letter, only do that for your classes. So your
Dialogparameter should be speltdialoginstead.A bigger point is what I said about where you define your methods and what
selfis. You have keptselfbeing your form, even when you are in code which is executing in the dialog. And you have member variables likeself.lineEditUser&self.lineEditPasswhich are for widgets on the dialog, even thoughselfis the form. This is not good for anybody.A much better pattern is to sub-class your dialog instance from
QDialog, and put the dialog's variables & methods in that sub-class, not in your form code which calls the dialog. (Oh, I see you have begun to do that, but not fully completed.) It will make your code much easier to understand & maintain in the long run. Your code should be written more like the following:class MyDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.btnReg.clicked.connect(self.register) def register(self): if self.lineEditUser.text() == "1" and self.lineEditPass.text()== "1": self.accept() def loginForm(self): self.dialog = MyDialog(self) ... if self.dialog.exec(): ....This assumes that
btnReg,lineEditUser&lineEditPassare all on the dialog. Note how we define theregister()method as a member of the dialog, not of the form, and duringregister()theselfrefers to the dialog itself, not the form. That's where it belongs.@JonB
I generated the dialog form via designer and it by default makes Dialog capitalized.def setupUi(self, Dialog): ........................................................... def setupUi(self, Form): Form.setObjectName("Form") Form.resize(400, 300)I really appreciate your hint and help.that was a grand help. I should use it as my correct workflow.
-
@Denni-0 said in Confirm login dialog and show main windows pyqt5:
if something I wrote internally is to be handed over to the general public for some reason -- then I need to go revisit it to make sure that it is okay to hand over to the general public
This is additional effort (especially when writing code in a company you hardly have any time for refactoring, was at least my experience so far).
But bigger issue is that you're getting used to your approach and need to switch to another one when writing code which is going to be shared with others."please keep that junk to yourself trolling is not appreciated here" - please stop talking this way to other people here! What is not appreciated here are personal attacks and insults! Just because somebody disagrees with you does not mean he/she is trolling! If I read this thread then I see that you're the one getting personal on other people...
-
@JonB
I generated the dialog form via designer and it by default makes Dialog capitalized.def setupUi(self, Dialog): ........................................................... def setupUi(self, Form): Form.setObjectName("Form") Form.resize(400, 300)I really appreciate your hint and help.that was a grand help. I should use it as my correct workflow.
I generated the dialog form via designer and it by default makes Dialog capitalized.
I am not a Creator user so I did not know that, sorry. Obviously I respect that you stuck with what it gave you. I find it a touch surprising, but there you are. Let's just say that the convention in both C++ & Python is to keep variables having lower-case start while classes have upper-case start, so if you look at examples here and on stackoverflow just be aware that is what you may see.