A subtle issue with QLabel
-
Hi all,
I'm going to design a login UI when a button clicked on the parent. There's also a label on it which shows a picture when login succeeds. It should work but not in practice. Please also review my code if it's not very good. Thanks.
LogDialog.h:#ifndef LOGDIALOG_H #define LOGDIALOG_H #include <QDialog> #include "userandpass.h" class QLabel; class QPushButton; class LogDialog : public QDialog { Q_OBJECT public: LogDialog(QWidget *parent = nullptr); void on_UsrPas_okBtn(const bool); private slots: void on_loginBtn(); private: QLabel* label = nullptr; QPushButton* login = nullptr; }; #endif // LOGDIALOG_HLogDialog.cpp:#include "logdialog.h" #include <QLabel> #include <QPushButton> #include <QVBoxLayout> #include <QMessageBox> LogDialog::LogDialog(QWidget *parent) : QDialog(parent) { login = new QPushButton(tr("Login")); label = new QLabel(tr("Not Logged In")); label->setAlignment(Qt::AlignCenter); auto mainLayout = new QVBoxLayout; mainLayout->addStretch(); mainLayout->addWidget(label); mainLayout->addStretch(); mainLayout->addWidget(login); setLayout(mainLayout); connect(login, &QPushButton::clicked, this, &LogDialog::on_loginBtn); } void LogDialog::on_loginBtn() { UserAndPass* log = new UserAndPass(this); log->exec(); delete log; } void LogDialog::on_UsrPas_okBtn(const bool m) { if(m){ label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false); } else { QMessageBox::critical(this, "Wrong Info", "You've entered wrong username and/or" "password.\n Try again!"); accept(); } }UserAndPass.h:#ifndef USERANDPASS_H #define USERANDPASS_H #include "logdialog.h" #include <QDialog> class QLineEdit; class QDialogButtonBox; class UserAndPass : public QDialog { Q_OBJECT; public: UserAndPass(QWidget *parent = nullptr); private slots: void on_Okbtn(); void on_Cancelbtn(); private: QLineEdit* usrLine = nullptr; QLineEdit* passLine = nullptr; QDialogButtonBox* btnBox = nullptr; const QString user = "user"; const QString pass = "pass"; }; #endif // USERANDPASS_HUserAndPass.cpp:#include "userandpass.h" #include <QDialogButtonBox> #include <QFormLayout> #include <QLineEdit> #include <QVBoxLayout> UserAndPass::UserAndPass(QWidget *parent) : QDialog(parent) { usrLine = new QLineEdit; passLine = new QLineEdit; passLine->setEchoMode(QLineEdit::Password); btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); auto form = new QFormLayout; form->addRow(tr("Username"), usrLine); form->addRow(tr("Password"), passLine); auto mainLayout = new QVBoxLayout; mainLayout->addLayout(form); mainLayout->addStretch(); mainLayout->addWidget(btnBox); setLayout(mainLayout); connect(btnBox, &QDialogButtonBox::accepted, this, &UserAndPass::on_Okbtn); connect(btnBox, &QDialogButtonBox::rejected, this, &UserAndPass::on_Cancelbtn); } void UserAndPass::on_Okbtn() { LogDialog ld; if(user == usrLine->text() && pass == passLine->text()) ld.on_UsrPas_okBtn(true); else ld.on_UsrPas_okBtn(false); accept(); } void UserAndPass::on_Cancelbtn() { reject(); }The problem is with
void LogDialog::on_UsrPas_okBtn(const bool m). Whilemistruebut these:label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false);won't work!
-
Hi
You could do it with signals & slot(pseudo code ish)
UserAndPass dialog1;
LogDialog ld;connect ( &dialog1, &UserAndPass ::YourNewSignal, &ld, LogDialog::on_UsrPas_okBtn)
ld.exec();Note that YourNewSignal must take bool as on_UsrPas_okBtn does.
Then in void UserAndPass::on_Okbtn()
{if(user == usrLine->text() && pass == passLine->text()) emit YourNewSignal(true); else emit YourNewSignal(false); accept();}
Hi
You could do it with signals & slot
UserAndPass dialog1;
LogDialog ld;Hi :)
The problem is with the number of instances. We have one for the parent (inmain.cpp) and one for the child (inLogDialog.cpp).I modified the code this way, and it works now as expected. But I still don't like it very much and hope there's a nicer way especially using the connections or an API.
LogDialog.h:#ifndef LOGDIALOG_H #define LOGDIALOG_H #include <QDialog> #include "userandpass.h" class QLabel; class QPushButton; class LogDialog : public QDialog { Q_OBJECT public: LogDialog(QWidget *parent = nullptr); private slots: void on_loginBtn(); private: QLabel* label = nullptr; QPushButton* login = nullptr; }; #endif // LOGDIALOG_HLogDialog.cpp:#include "logdialog.h" #include <QLabel> #include <QPushButton> #include <QVBoxLayout> #include <QMessageBox> LogDialog::LogDialog(QWidget *parent) : QDialog(parent) { login = new QPushButton(tr("Login")); label = new QLabel(tr("Not Logged In")); label->setAlignment(Qt::AlignCenter); auto mainLayout = new QVBoxLayout; mainLayout->addStretch(); mainLayout->addWidget(label); mainLayout->addStretch(); mainLayout->addWidget(login); setLayout(mainLayout); connect(login, &QPushButton::clicked, this, &LogDialog::on_loginBtn); } void LogDialog::on_loginBtn() { UserAndPass* log = new UserAndPass(this); log->exec(); if(log->getOkBtnCld() && log->getMatch()) { label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false); } else if(log->getOkBtnCld() && !log->getMatch()) QMessageBox::critical(this, "Wrong Info", "You've entered wrong username and/or" "password.\n Try again!"); delete log; }UserAndPass.h:#ifndef USERANDPASS_H #define USERANDPASS_H #include "logdialog.h" #include <QDialog> class QLineEdit; class QDialogButtonBox; class UserAndPass : public QDialog { Q_OBJECT; public: UserAndPass(QWidget *parent = nullptr); bool getMatch() const; void setMatch(bool value); bool getOkBtnCld() const; void setOkBtnCld(bool value); private slots: void on_Okbtn(); void on_Cancelbtn(); private: QLineEdit* usrLine = nullptr; QLineEdit* passLine = nullptr; QDialogButtonBox* btnBox = nullptr; const QString user = "user"; const QString pass = "pass"; bool match = false; bool okBtnCld = false; }; #endif // USERANDPASS_HUserAndPass.cpp:#include "userandpass.h" #include <QDialogButtonBox> #include <QFormLayout> #include <QLineEdit> #include <QVBoxLayout> UserAndPass::UserAndPass(QWidget *parent) : QDialog(parent) { usrLine = new QLineEdit; passLine = new QLineEdit; passLine->setEchoMode(QLineEdit::Password); btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); auto form = new QFormLayout; form->addRow(tr("Username"), usrLine); form->addRow(tr("Password"), passLine); auto mainLayout = new QVBoxLayout; mainLayout->addLayout(form); mainLayout->addStretch(); mainLayout->addWidget(btnBox); setLayout(mainLayout); connect(btnBox, &QDialogButtonBox::accepted, this, &UserAndPass::on_Okbtn); connect(btnBox, &QDialogButtonBox::rejected, this, &UserAndPass::reject); } void UserAndPass::on_Okbtn() { setOkBtnCld(true); if(user == usrLine->text() && pass == passLine->text()) setMatch(true); accept(); } bool UserAndPass::getOkBtnCld() const { return okBtnCld; } void UserAndPass::setOkBtnCld(bool value) { okBtnCld = value; } bool UserAndPass::getMatch() const { return match; } void UserAndPass::setMatch(bool value) { match = value; } -
Hi all,
I'm going to design a login UI when a button clicked on the parent. There's also a label on it which shows a picture when login succeeds. It should work but not in practice. Please also review my code if it's not very good. Thanks.
LogDialog.h:#ifndef LOGDIALOG_H #define LOGDIALOG_H #include <QDialog> #include "userandpass.h" class QLabel; class QPushButton; class LogDialog : public QDialog { Q_OBJECT public: LogDialog(QWidget *parent = nullptr); void on_UsrPas_okBtn(const bool); private slots: void on_loginBtn(); private: QLabel* label = nullptr; QPushButton* login = nullptr; }; #endif // LOGDIALOG_HLogDialog.cpp:#include "logdialog.h" #include <QLabel> #include <QPushButton> #include <QVBoxLayout> #include <QMessageBox> LogDialog::LogDialog(QWidget *parent) : QDialog(parent) { login = new QPushButton(tr("Login")); label = new QLabel(tr("Not Logged In")); label->setAlignment(Qt::AlignCenter); auto mainLayout = new QVBoxLayout; mainLayout->addStretch(); mainLayout->addWidget(label); mainLayout->addStretch(); mainLayout->addWidget(login); setLayout(mainLayout); connect(login, &QPushButton::clicked, this, &LogDialog::on_loginBtn); } void LogDialog::on_loginBtn() { UserAndPass* log = new UserAndPass(this); log->exec(); delete log; } void LogDialog::on_UsrPas_okBtn(const bool m) { if(m){ label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false); } else { QMessageBox::critical(this, "Wrong Info", "You've entered wrong username and/or" "password.\n Try again!"); accept(); } }UserAndPass.h:#ifndef USERANDPASS_H #define USERANDPASS_H #include "logdialog.h" #include <QDialog> class QLineEdit; class QDialogButtonBox; class UserAndPass : public QDialog { Q_OBJECT; public: UserAndPass(QWidget *parent = nullptr); private slots: void on_Okbtn(); void on_Cancelbtn(); private: QLineEdit* usrLine = nullptr; QLineEdit* passLine = nullptr; QDialogButtonBox* btnBox = nullptr; const QString user = "user"; const QString pass = "pass"; }; #endif // USERANDPASS_HUserAndPass.cpp:#include "userandpass.h" #include <QDialogButtonBox> #include <QFormLayout> #include <QLineEdit> #include <QVBoxLayout> UserAndPass::UserAndPass(QWidget *parent) : QDialog(parent) { usrLine = new QLineEdit; passLine = new QLineEdit; passLine->setEchoMode(QLineEdit::Password); btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); auto form = new QFormLayout; form->addRow(tr("Username"), usrLine); form->addRow(tr("Password"), passLine); auto mainLayout = new QVBoxLayout; mainLayout->addLayout(form); mainLayout->addStretch(); mainLayout->addWidget(btnBox); setLayout(mainLayout); connect(btnBox, &QDialogButtonBox::accepted, this, &UserAndPass::on_Okbtn); connect(btnBox, &QDialogButtonBox::rejected, this, &UserAndPass::on_Cancelbtn); } void UserAndPass::on_Okbtn() { LogDialog ld; if(user == usrLine->text() && pass == passLine->text()) ld.on_UsrPas_okBtn(true); else ld.on_UsrPas_okBtn(false); accept(); } void UserAndPass::on_Cancelbtn() { reject(); }The problem is with
void LogDialog::on_UsrPas_okBtn(const bool m). Whilemistruebut these:label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false);won't work!
void UserAndPass::on_Okbtn() { LogDialog ld; if(user == usrLine->text() && pass == passLine->text()) ld.on_UsrPas_okBtn(true); else ld.on_UsrPas_okBtn(false); accept(); }This creates a local
LogDialog, then exits taking it with it. The stuff you do inLogDialog::on_UsrPas_okBtn()won't be seen. I don't know what you're trying to do here, just think through the logic. -
@tomy said in A subtle issue with QLabel:
LogDialog ld;
C basics - you're creating a new, local instance and using this instead the previous instantiated one.
-
void UserAndPass::on_Okbtn() { LogDialog ld; if(user == usrLine->text() && pass == passLine->text()) ld.on_UsrPas_okBtn(true); else ld.on_UsrPas_okBtn(false); accept(); }This creates a local
LogDialog, then exits taking it with it. The stuff you do inLogDialog::on_UsrPas_okBtn()won't be seen. I don't know what you're trying to do here, just think through the logic.I guess I got the bug; two different objects.
What I'm trying to do is to call the function
LogDialog::on_UsrPas_okBtn()from the functionvoid UserAndPass::on_Okbtn()when theOKbutton is clicked. That is, somehow to be able to connect the two objects of two different classes (one the child of the other). I'm sure there's a pretty easy way for that. I could do the stuff:label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false);in the
void LogDialog::on_loginBtn(). But I want to do them when the buttonOKis clicked not at any circumstances. Is it clear what I'm trying to say, please? -
Hi
You could do it with signals & slot(pseudo code ish)
UserAndPass dialog1;
LogDialog ld;connect ( &dialog1, &UserAndPass ::YourNewSignal, &ld, LogDialog::on_UsrPas_okBtn)
ld.exec();Note that YourNewSignal must take bool as on_UsrPas_okBtn does.
Then in void UserAndPass::on_Okbtn()
{if(user == usrLine->text() && pass == passLine->text()) emit YourNewSignal(true); else emit YourNewSignal(false); accept();}
-
Hi
You could do it with signals & slot(pseudo code ish)
UserAndPass dialog1;
LogDialog ld;connect ( &dialog1, &UserAndPass ::YourNewSignal, &ld, LogDialog::on_UsrPas_okBtn)
ld.exec();Note that YourNewSignal must take bool as on_UsrPas_okBtn does.
Then in void UserAndPass::on_Okbtn()
{if(user == usrLine->text() && pass == passLine->text()) emit YourNewSignal(true); else emit YourNewSignal(false); accept();}
Hi
You could do it with signals & slot
UserAndPass dialog1;
LogDialog ld;Hi :)
The problem is with the number of instances. We have one for the parent (inmain.cpp) and one for the child (inLogDialog.cpp).I modified the code this way, and it works now as expected. But I still don't like it very much and hope there's a nicer way especially using the connections or an API.
LogDialog.h:#ifndef LOGDIALOG_H #define LOGDIALOG_H #include <QDialog> #include "userandpass.h" class QLabel; class QPushButton; class LogDialog : public QDialog { Q_OBJECT public: LogDialog(QWidget *parent = nullptr); private slots: void on_loginBtn(); private: QLabel* label = nullptr; QPushButton* login = nullptr; }; #endif // LOGDIALOG_HLogDialog.cpp:#include "logdialog.h" #include <QLabel> #include <QPushButton> #include <QVBoxLayout> #include <QMessageBox> LogDialog::LogDialog(QWidget *parent) : QDialog(parent) { login = new QPushButton(tr("Login")); label = new QLabel(tr("Not Logged In")); label->setAlignment(Qt::AlignCenter); auto mainLayout = new QVBoxLayout; mainLayout->addStretch(); mainLayout->addWidget(label); mainLayout->addStretch(); mainLayout->addWidget(login); setLayout(mainLayout); connect(login, &QPushButton::clicked, this, &LogDialog::on_loginBtn); } void LogDialog::on_loginBtn() { UserAndPass* log = new UserAndPass(this); log->exec(); if(log->getOkBtnCld() && log->getMatch()) { label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false); } else if(log->getOkBtnCld() && !log->getMatch()) QMessageBox::critical(this, "Wrong Info", "You've entered wrong username and/or" "password.\n Try again!"); delete log; }UserAndPass.h:#ifndef USERANDPASS_H #define USERANDPASS_H #include "logdialog.h" #include <QDialog> class QLineEdit; class QDialogButtonBox; class UserAndPass : public QDialog { Q_OBJECT; public: UserAndPass(QWidget *parent = nullptr); bool getMatch() const; void setMatch(bool value); bool getOkBtnCld() const; void setOkBtnCld(bool value); private slots: void on_Okbtn(); void on_Cancelbtn(); private: QLineEdit* usrLine = nullptr; QLineEdit* passLine = nullptr; QDialogButtonBox* btnBox = nullptr; const QString user = "user"; const QString pass = "pass"; bool match = false; bool okBtnCld = false; }; #endif // USERANDPASS_HUserAndPass.cpp:#include "userandpass.h" #include <QDialogButtonBox> #include <QFormLayout> #include <QLineEdit> #include <QVBoxLayout> UserAndPass::UserAndPass(QWidget *parent) : QDialog(parent) { usrLine = new QLineEdit; passLine = new QLineEdit; passLine->setEchoMode(QLineEdit::Password); btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); auto form = new QFormLayout; form->addRow(tr("Username"), usrLine); form->addRow(tr("Password"), passLine); auto mainLayout = new QVBoxLayout; mainLayout->addLayout(form); mainLayout->addStretch(); mainLayout->addWidget(btnBox); setLayout(mainLayout); connect(btnBox, &QDialogButtonBox::accepted, this, &UserAndPass::on_Okbtn); connect(btnBox, &QDialogButtonBox::rejected, this, &UserAndPass::reject); } void UserAndPass::on_Okbtn() { setOkBtnCld(true); if(user == usrLine->text() && pass == passLine->text()) setMatch(true); accept(); } bool UserAndPass::getOkBtnCld() const { return okBtnCld; } void UserAndPass::setOkBtnCld(bool value) { okBtnCld = value; } bool UserAndPass::getMatch() const { return match; } void UserAndPass::setMatch(bool value) { match = value; } -
@tomy said in A subtle issue with QLabel:
But I still don't like it very much
It's exactly like a modal dialog should be used.
-
hi
Nothing dirty with nested dialogs
but why notvoid LogDialog::on_loginBtn() { UserAndPass log(this); log.exec(); if(log.getOkBtnCld() && log.getMatch()) { label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false); } else if(log.getOkBtnCld() && !log.getMatch()) QMessageBox::critical(this, "Wrong Info", "You've entered wrong username and/or" "password.\n Try again!"); }There is no need (or benefit) to new it here
and we can get rid of
delete log;
which we could end up forgetting calling if we add to code later. -
hi
Nothing dirty with nested dialogs
but why notvoid LogDialog::on_loginBtn() { UserAndPass log(this); log.exec(); if(log.getOkBtnCld() && log.getMatch()) { label->setPixmap(QPixmap(":/files/Image/QtTomy.png")); login->setText("Welcome"); login->setEnabled(false); } else if(log.getOkBtnCld() && !log.getMatch()) QMessageBox::critical(this, "Wrong Info", "You've entered wrong username and/or" "password.\n Try again!"); }There is no need (or benefit) to new it here
and we can get rid of
delete log;
which we could end up forgetting calling if we add to code later.