D
Dragon001Сәуір 19, 2017, 5:29 Т.Қ.

Ошибка соединения

Здравствуйте. Делаю программу, в которой идет сначала авторизация в БД по логин/паролю, после чего, относительно того какая роль, открывает определенно окно, после открытия окна(для Администратора) производится запись в 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);

}

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

3
Evgenii Legotckoi
  • Сәуір 20, 2017, 2:37 Т.Ж.

У вас путаница с последовательностью действий. Нужно сделать авторизацию. И передать дальше управление в другое окно. Но при этом сам объект базы данных существует локально в методе on_EnterButton_clicked() . db сохраняется в стеке и не существует в другом окне, скорее всего соединение падает при окончании работы метода on_EnterButton_clicked() . Лучше делать обёртку, для работы с подключением к базе данных. Создать объект этой обертки к базе данных и через метод подключения передать по сигналам данные для авторизации. Также стоит выделить память через new для этого объекта обёртки. Класс обёртки у меня есть в следующей статье . Там есть метод connectToDataBase() , можете его переделать, чтобы он принимал в качестве аргументов пароль, логин и т.д. А возвращал например роль. Что касается передачи информации между окнами, то можете посмотреть вот этот пример . Там окна взаимодействуют через сигналы и слоты, как раз то, что нужно, чтобы вернуть данные из кона авторизации в главное окно.

Что касается использования QMainWindow, то можно использовать в качестве окна даже простой QWidget, но QDialog имеет уже встроенные стандартные кнопки.

Вообще, сам вот этот код должен быть в неком ядре программы, а не в конкретном окне.

QSqlDatabase db=QSqlDatabase::addDatabase("QPSQL");

db.setHostName(host);
db.setPort(port);
db.setDatabaseName(base);
db.setUserName(ui->login->text());
db.setPassword(ui->password->text());

db.open()

Окошко авторизации должно лишь получать данные и передавать его для авторизации в обёртку для работы с базой данных. Обёртка должна выполнять функционал шаблона проектирования фасад и быть API для работы с базой данных по максимуму, настолько, насколько это возможно.

    D
    • Сәуір 20, 2017, 2:52 Т.Қ.

    Я нашел ошибку у себя, у меня получалось, что я создавал объект main окно до соединения с БД, из-за этого писало ошибку, переместил строку AdminForm = new AdministrationForm(); и все заработало, но перед этим сделал как вы просили, сделал отдельный класс для соединения с бд,в которую передавал значения и принимал. Я так понимаю верным должен быть 2 вариант, но почему? Разве объект БД не будет существовать до окончания программы?

      Evgenii Legotckoi
      • Сәуір 20, 2017, 11:45 Т.Қ.
      • Жауап шешім ретінде белгіленді.

      Когда вы вызываете данный метод:

      QSqlDatabase db=QSqlDatabase::addDatabase("QPSQL");

      Вы сохраняете объект базы данных в стеке, то есть объект существует локально внутри метода on_EnterButton_clicked . А что происходит со всеми локальными переменными, когда метод заканчивает свою работу? Правильно, они уничтожаются. А вместе с этим уничтожением закрывается соединение с базой данных. Почему оно закрывается? Потому что локальный объект уничтожен и память освобождена. Хорошо, что ещё Segmentation Fault не словили.

      Конечно, в случае с QSqlDataBase всё обстоит хитрее, там несколько сложнее всё сделано внутри, поскольку сохраняются имена соединений, но, как я считаю, работать базаданных будет до тех пор, пока под неё выделена память. В конце концов QSqlDataBase хранит логин, пароль, порт, IP и т.д, а если память была освобождена, то куда это всё будет помещено? Никуда, пропадёт. Поэтому лучше держать базу данных за фассадом-обёрткой, чтобы всегда была выделена память под объект базы данных. В моём варианте с обёрткой, память выделенная под базу данных существует до конца работы программы.

        Пікірлер

        Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
        Кіріңіз немесе Тіркеліңіз
        Г

        C++ - Тест 001. Первая программа и типы данных

        • Нәтиже:66ұпай,
        • Бағалау ұпайлары-1
        t

        C++ - Тест 001. Первая программа и типы данных

        • Нәтиже:33ұпай,
        • Бағалау ұпайлары-10
        t

        Qt - Тест 001. Сигналы и слоты

        • Нәтиже:52ұпай,
        • Бағалау ұпайлары-4
        Соңғы пікірлер
        G
        GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
        Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
        d
        dblas5Шілде 5, 2024, 11:02 Т.Ж.
        QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
        k
        kmssrАқп. 8, 2024, 6:43 Т.Қ.
        Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
        АК
        Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
        Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
        Енді форумда талқылаңыз
        Evgenii Legotckoi
        Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
        добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
        F
        FynjyШілде 22, 2024, 4:15 Т.Ж.
        при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
        BlinCT
        BlinCTМаусым 25, 2024, 1 Т.Ж.
        Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
        BlinCT
        BlinCTМамыр 5, 2024, 5:46 Т.Ж.
        Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
        Evgenii Legotckoi
        Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
        Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

        Бізді әлеуметтік желілерде бақылаңыз