У меня есть главное окно приложения BankSystem
#include "session.h"
#include "registration.h"
#include "login.h"
class BankSystem : public QMainWindow
{
Q_OBJECT
public:
BankSystem(QWidget *parent = nullptr);
~BankSystem();
Login* getLogin();
private:
Ui::BankSystem *ui;
Login *login;
Registration *registration;
Session* _currentSession;
};
Есть указатель на класс Login
. При запуске приложения первым запускается окно входа, т.е. Login
и, если авторизация прошла успешна, я должен засетать текущую сессию. У меня стоит слот, который отлавливает событие нажатия на кнопку Войти
. И тут возникает проблема, как из этого слота засетать текущую сессию? Или как изменить логику, чтобы такая операция стала возможной?
#include "banksystem.h"
BankSystem::BankSystem(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::BankSystem)
{
ui->setupUi(this);
login = new Login();
}
Класс Login
class Login : public QWidget
{
Q_OBJECT
public:
explicit Login(QWidget *parent = nullptr);
~Login();
private slots:
void on_loginButton_clicked();
void on_registrationButton_clicked();
private:
Ui::Login *ui;
};
#include "login.h"
void Login::on_loginButton_clicked()
{
if (ui->loginSection->text().isEmpty()
|| ui->passwordSection->text().isEmpty())
{
QMessageBox msgBox;
msgBox.setText("Необходимо ввести логин и пароль!");
msgBox.setIcon(QMessageBox::Icon::Information);
msgBox.exec();
return;
}
QString login = ui->loginSection->text();
QString password = ui->passwordSection->text();
try {
// Вот тут мне нужно засетать сессию
} catch (std::exception& e) {
qDebug() << e.what();
}
}
1) Создаем в классе Login
сигнал loginOk
signals:
void loginOk();
2) Высылаем сигнал при успехе в Login::on_loginButton_clicked()
:
void Login::on_loginButton_clicked()
{
...
emit loginOk();
...
}
3) Создаем слот BankSystem::onLoginOk()
:
public slots:
void onLoginOk();
4) В котором и "сетим" сессию:
void BankSystem::onLoginOk()
{
...
session->set(true); //не знаю, как у вас
//опционально удаляем сендер с помощью deleteLater()
...
}
5) Соединяем сигнал и слот:
connect(login, &Login::loginOk, bankSystem, &BankSystem::onLoginOk);
6) Радуемся работе программы
Такой подход наиболее каноничен, православен и кошерен с точки зрения QT. Соединив объекты один раз, больше не надо заботится об их взаимодействии и взаимных вызовах, каждый объект будет жить своей автономной жизнью, а взаимодействие будет происходить автоматически. К тому же, не требуется использовать указатель на Login
в качестве члена BankSystem
. Таким же способом можно соединить Registration
и Login
.
Замечу, хоть и не относится к вопросу: Если требуется более-менее сложная логика логинга, сессий и регистрации, я бы выделил отдельные классы для логинга, сессии, креденциалов и регистрации и для соответсвующих окон логинга и регистрации, вместо вкладывать логику в виджетные классы. Для простой проверки в стиле if (password == "iloveu")
- сойдет
Вам класс логин нужен на один раз, так зачем его вообще создавать через указатель?
Лучше создавать и вызывать в модальном режиме в локальной памяти, для этого надо использовать QEventLoop
:
class Login ... {
public:
Login() {
isLogged = false;
connect(ui->buttonOk, Login::yes, [=]() {
isLogged = true;
_loop.quit();
});
}
bool exec() {
_loop.exec();
return _isLogged;
}
QEventLoop _loop;
bool _isLogged;
}
Теперь в main.cpp:
... main() {
...
Login login;
bool isLogged = login.exec();
// Или, если надо дать пользователю шанс исправить ввод:
while(isLogged = login.exec()) {
login.setErrorMessage("Попробуйте еще раз!");
}
// Можно ограничить количество попыток и так далее
// Кроме того, этот while лучше перенести внутрь exec() и
// там уже реализовать необходимую логику,
// но это вопрос вашей архитектуры
if( _isLooged ) {
BankSystem w;
w.show();
return a.exec();
}
return 0;
}
Теперь видно, что сессию, например, можно стартонуть прямо из конструктора главного окна приложения:
class BankSystem : ... {
...
public:
BankSystem() {
_session->start();
}
}
А можно, если нужно проверять состояние сессии, сделать отдельный метод:
class BankSystem {
void sessionStart() {
if( !_session->start() ) {
// Сессия не запустилась, надо что-то делать
}
}
}
Я рекомендую вам сделать класс сессии синглтоном, так как обычно сессией управляет один объект, а сверять и изменять ее состояние вероятно понадобится из разных функций и методов, разной степени вложенности:
class Session {
public:
static Session& instance() {
return self == null? self = new Session(): self;
}
private:
Session* self;
}
Теперь в любом месте программы, в любом методе:
Session::instance().<какая-то функция>
И не надо будет думать о бесконечных вызовах и коннектов
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Разбираюсь с template-ми на c++Написал небольшую функцию которая принимает, какой-то объект MyJSON* _value и в реализации сделал разбор в зависимости...
Здраствуйте, пробую реализовать арканоид, но столкнулся с проблемой, что текстуры привязуется к не правильным участкам пространстваУ меня...