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_H
LogDialog.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_H
UserAndPass.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)
. Whilem
istrue
but 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_H
LogDialog.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_H
UserAndPass.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_H
LogDialog.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_H
UserAndPass.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)
. Whilem
istrue
but 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 theOK
button 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 buttonOK
is 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_H
LogDialog.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_H
UserAndPass.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.