Ошибка соединения
Здравствуйте. Делаю программу, в которой идет сначала авторизация в БД по логин/паролю, после чего, относительно того какая роль, открывает определенно окно, после открытия окна(для Администратора) производится запись в TableView. Если писать соединение сразу в main.cpp, то все прекрасно отображает,но у меня идет соединение через форму enterform. Если произвожу авторизацию через нее, то возникает такое окошко(Driver not loaded) и соответственно выборка не производится, но открывает нужное окно, где есть кнопка "Найти", после нажатия на которую, производится выборка. Я так понимаю, авторизация происходит как бы позже. Тогда возникает такой вопрос? Как это сделать правильно? Думал использовать QDialog,но как возвратит строку обратно в main.cpp? Или возможно ли не использовать QMainWindow(если допустим не нужны меню и прочее?) или он обязателен?
enterform::enterform(QWidget *parent) : QDialog(parent), ui(new Ui::enterform) { ui->setupUi(this); //AdminForm = new AdministrationForm(); QSettings settings("SOK", "Connection"); ui->savecheckbox->setChecked(settings.value("saveSetting", false).toBool()); if (ui->savecheckbox->isChecked()) { QString user=settings.value("user").toString(); QString pass=settings.value("pass").toString(); ui->login->setText(user); ui->password->setText(pass); } } enterform::~enterform() { delete ui; } void enterform::on_EnterButton_clicked(){ AdminForm = new AdministrationForm(); QSettings settings("SOK", "Connection"); QString host=settings.value("host").toString(); int port=settings.value("port").toInt(); QString base=settings.value("base").toString(); QSqlDatabase db=QSqlDatabase::addDatabase("QPSQL"); db.setHostName(host); db.setPort(port); db.setDatabaseName(base); db.setUserName(ui->login->text()); db.setPassword(ui->password->text()); if (db.open()) { QSqlQuery query; if (ui->savecheckbox->isChecked()){ settings.setValue("saveSetting", true); settings.setValue("user", ui->login->text()); settings.setValue("pass",ui->password->text()); query.exec("SELECT r.rolname FROM pg_catalog.pg_auth_members m, pg_catalog.pg_roles r WHERE m.roleid=r.oid and m.member =(SELECT oid FROM pg_catalog.pg_roles WHERE rolname = '"+ui->login->text()+"');"); while (query.next()) { QString rolname = query.value(0).toString(); if (rolname == "Administation") { this->close(); AdminForm->showMaximized(); } else if(rolname == "director") { qDebug() << "test"; } } } else { settings.setValue("saveSetting", false); settings.setValue("user", ui->login->text()); this->close(); } } else { QMessageBox::warning(0, QObject::tr("Error"), db.lastError().databaseText()); } }
#include "administrationform.h" #include "ui_administrationform.h" #include <QTableView> #include <QSqlError> #include <QMessageBox> AdministrationForm::AdministrationForm(QWidget *parent) : QMainWindow(parent), ui(new Ui::AdministrationForm) { ui->setupUi(this); AllClientSelect(); } AdministrationForm::~AdministrationForm() { delete ui; } void AdministrationForm::AllClientSelect() { allClienttable = new QSqlQueryModel(this); allClienttable->setQuery("SELECT nomer_abonementa,familiya,imya,otchestvo,end_ref,mobile FROM klient"); if (allClienttable->lastError().isValid()) { QMessageBox::information(this, tr("TestErr"), allClienttable->lastError().databaseText()); } allClienttable->setHeaderData(0, Qt::Horizontal, tr("Номер Абонемента")); allClienttable->setHeaderData(1, Qt::Horizontal, tr("Фамилия")); allClienttable->setHeaderData(2, Qt::Horizontal, tr("Имя")); allClienttable->setHeaderData(3, Qt::Horizontal, tr("Отчество")); allClienttable->setHeaderData(4, Qt::Horizontal, tr("Конец справки")); allClienttable->setHeaderData(5, Qt::Horizontal, tr("Телефон")); ui->allClient->setModel(allClienttable); ui->allClient->setSelectionBehavior(QAbstractItemView::SelectRows); ui->allClient->setColumnHidden(0, true); ui->allClient->setEditTriggers(QAbstractItemView::NoEditTriggers); } void AdministrationForm::on_pushButton_5_clicked() { allClienttable = new QSqlQueryModel(this); allClienttable->setQuery("SELECT nomer_abonementa,familiya,imya,otchestvo,end_ref,mobile FROM klient"); allClienttable->setHeaderData(0, Qt::Horizontal, tr("Номер Абонемента")); allClienttable->setHeaderData(1, Qt::Horizontal, tr("Фамилия")); allClienttable->setHeaderData(2, Qt::Horizontal, tr("Имя")); allClienttable->setHeaderData(3, Qt::Horizontal, tr("Отчество")); allClienttable->setHeaderData(4, Qt::Horizontal, tr("Конец справки")); allClienttable->setHeaderData(5, Qt::Horizontal, tr("Телефон")); ui->allClient->setModel(allClienttable); //Разрешаем выделение строк ui->allClient->setSelectionBehavior(QAbstractItemView::SelectRows); ui->allClient->resizeColumnsToContents(); ui->allClient->setEditTriggers(QAbstractItemView::NoEditTriggers); }
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.Do you like it? Share on social networks!
- Akiv Doros
- Nov. 11, 2024, 10:58 p.m.
C ++ - Test 004. Pointers, Arrays and Loops
- Result:50points,
- Rating points-4
- molni99
- Oct. 26, 2024, 8:37 a.m.
C ++ - Test 004. Pointers, Arrays and Loops
- Result:80points,
- Rating points4
- molni99
- Oct. 26, 2024, 8:29 a.m.
C ++ - Test 004. Pointers, Arrays and Loops
- Result:20points,
- Rating points-10
У вас путаница с последовательностью действий. Нужно сделать авторизацию. И передать дальше управление в другое окно. Но при этом сам объект базы данных существует локально в методе on_EnterButton_clicked() . db сохраняется в стеке и не существует в другом окне, скорее всего соединение падает при окончании работы метода on_EnterButton_clicked() . Лучше делать обёртку, для работы с подключением к базе данных. Создать объект этой обертки к базе данных и через метод подключения передать по сигналам данные для авторизации. Также стоит выделить память через new для этого объекта обёртки. Класс обёртки у меня есть в следующей статье . Там есть метод connectToDataBase() , можете его переделать, чтобы он принимал в качестве аргументов пароль, логин и т.д. А возвращал например роль. Что касается передачи информации между окнами, то можете посмотреть вот этот пример . Там окна взаимодействуют через сигналы и слоты, как раз то, что нужно, чтобы вернуть данные из кона авторизации в главное окно.
Что касается использования QMainWindow, то можно использовать в качестве окна даже простой QWidget, но QDialog имеет уже встроенные стандартные кнопки.
Вообще, сам вот этот код должен быть в неком ядре программы, а не в конкретном окне.
Окошко авторизации должно лишь получать данные и передавать его для авторизации в обёртку для работы с базой данных. Обёртка должна выполнять функционал шаблона проектирования фасад и быть API для работы с базой данных по максимуму, настолько, насколько это возможно.
Я нашел ошибку у себя, у меня получалось, что я создавал объект main окно до соединения с БД, из-за этого писало ошибку, переместил строку AdminForm = new AdministrationForm(); и все заработало, но перед этим сделал как вы просили, сделал отдельный класс для соединения с бд,в которую передавал значения и принимал. Я так понимаю верным должен быть 2 вариант, но почему? Разве объект БД не будет существовать до окончания программы?
Когда вы вызываете данный метод:
Вы сохраняете объект базы данных в стеке, то есть объект существует локально внутри метода on_EnterButton_clicked . А что происходит со всеми локальными переменными, когда метод заканчивает свою работу? Правильно, они уничтожаются. А вместе с этим уничтожением закрывается соединение с базой данных. Почему оно закрывается? Потому что локальный объект уничтожен и память освобождена. Хорошо, что ещё Segmentation Fault не словили.
Конечно, в случае с QSqlDataBase всё обстоит хитрее, там несколько сложнее всё сделано внутри, поскольку сохраняются имена соединений, но, как я считаю, работать базаданных будет до тех пор, пока под неё выделена память. В конце концов QSqlDataBase хранит логин, пароль, порт, IP и т.д, а если память была освобождена, то куда это всё будет помещено? Никуда, пропадёт. Поэтому лучше держать базу данных за фассадом-обёрткой, чтобы всегда была выделена память под объект базы данных. В моём варианте с обёрткой, память выделенная под базу данных существует до конца работы программы.