Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB
24 июня 2018 г. 14:10

QComboBox и База данных

Qt, DataBase, QComboBox

Добрый день.

Необходима помощь в работе с QComboBox в связке с базой данных.

Описание:

Есть две таблицы:

1) "extension" с полями: id, library, function, ext.
2) "ext_type" с полями: id, type.

Таблицы связаны по полям ext и type. В первую таблицу в поле ext записывается id из второй таблицы.

В главном окне расположена таблица в которой отображаются данные из таблицы extension, в поле ext  подставляется вместо id соответствующий type из таблицы "ext_type".

Код:


mainModel = new QSqlRelationalTableModel(this);
mainModel->setTable("extension");

mainModel->setSort(0, Qt::AscendingOrder);
ui->mainTableView->setModel(mainModel);

// Выбор extension с таблицы ext_type по id
mainModel->setRelation(3, QSqlRelation("ext_type", "id", "type"));
ui->mainTableView->setItemDelegate(new QSqlRelationalDelegate(ui->mainTableView));
mainModel->select();

ui->mainTableView->setColumnHidden(0, true);

for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
 ui->mainTableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch);
}
Все подставляется хорошо.

Второе окно открывается при редактировании записи в таблице или создании новой. На нем расположены QLineEdit для полей library, function и QComboBox для поля extension.

Нужно чтобы при создании новой записи из QComboBox пользователь мог выбрать значения из поля type таблицы ext_type.


Сделал так (под выбор работает а при редактировании существующей записи в QComboBox появляется не та строка):

ОШИБКА ЗДЕСЬ:

model = new QSqlTableModel(this);

mapper = new QDataWidgetMapper();
mapper->setModel(model);

mapper->addMapping(ui->Line1, 1);
mapper->addMapping(ui->Line2, 2);

QSqlQueryModel *select = new QSqlQueryModel(this);
select->setQuery("select type from ext_type");
ui->comboBox->setModel(select);

mapper->addMapping(ui->comboBox, model->fieldIndex("extension"), "currentIndex");

mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);

mapper->toLast();
Сохранение так (сохраняет, но из comboBox в таблицу попадает не та запись (см. выше)):

mapper->submit();
model->submitAll();

model->select();
mapper->toLast();
Помогите решить проблему.

И почему-то
mainModel->setRelation(3, QSqlRelation("ext_type", "id", "type"));
с таблицами выше работает.

А в этом случае нет:

mainModel = new QSqlRelationalTableModel(this);
mainModel->setTable("security_question");

mainModel->setSort(0, Qt::AscendingOrder);
ui->mainTableView->setModel(mainModel);

// Здесь
mainModel->setRelation(1, QSqlRelation("question", "id", "type"));
ui->mainTableView->setItemDelegate(new QSqlRelationalDelegate(ui->mainTableView));
mainModel->select();

ui->mainTableView->setColumnHidden(0, true);

for (int i = 0; i < ui->mainTableView->horizontalHeader()->count(); i++) {
ui->mainTableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch);
}
В таблицу на форме  вообще не выводятся данные (в сама таблица в базе данных заполнена).

Структура таблиц:
1) Таблица security_question: id, SecurityQuestion, Answer.
2) Таблица question: id, type.

Что может быль не так?

И подскажите как возможно организовать в базе данных запись в поле таблицы типа result1 или result2 в зависимости от того, какой QRadioButton пользователь выбрал на форме. А также, чтобы при редактировании данных на форме включался нужный QRadioButton в зависимости от записи?

В этом случае пока ничего не придумал.

Заранее спасибо за ответ и извините за долгое и возможно немного не понятное описание вопроса.
























19
  • 24 июня 2018 г. 14:27
  • Ответ был помечен как решение.

Насчет этого:

И почему-то
mainModel->setRelation(3, QSqlRelation("ext_type", "id", "type"));
с таблицами выше работает.

Извините вопрос снят, ошибся. В базе данных на поле SecurityQuestion вместо integer поставил тип text.
1
  • 25 июня 2018 г. 8:47
На форумах нашел такой подход:


mapper->addMapping(ui->comboBox, model->fieldIndex("extension")); 

Но это вообще не работает.
0

Вообще должно работать, но там немного нюансы есть, к сожалению уже и не помню какие.

0
  • 25 июня 2018 г. 9:50
  • (ред.)
Оно то работает только:


В базе данных в столбце (например):

id                            type

1                             data
2                             key
3                             stat

В таблице главного окна:


Столбцы ......... .............. ....... ext

......... .............. ...... data
......... .............. ....... stat
......... .............. ....... key


А в ComboBox при редактировании записи 2 вмето "stat" выходит "data".
0
  • 25 июня 2018 г. 9:56
То есть запись по индексу выпадает на единицу меньше чем должна. Подозреваю ошибка здесь:

mapper->addMapping(ui->comboBox, model->fieldIndex("extension"), "currentIndex");
id записи в базе не совпадает с ее номером в comboBox. Но при попытке указать вместо currentIndex что-то другое, то вообще перестает работать.



0
  • 25 июня 2018 г. 12:03
Нашел решение:

model = new QSqlRelationalTableModel(this);
model->setTable(TABLE);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->setSort(0, Qt::AscendingOrder);

int typeIndex = model->fieldIndex("ext_type");
model->setRelation(typeIndex, QSqlRelation("extension_type", "id", "type"));
model->select();

QSqlTableModel *relModel = model->relationModel(typeIndex);
ui->extTypeBox->setModel(relModel);
ui->extTypeBox->setModelColumn(relModel->fieldIndex("type"));

mapper = new QDataWidgetMapper(this);
mapper->setModel(model);
mapper->setItemDelegate(new QSqlRelationalDelegate(this));

mapper->addMapping(ui->extTypeBox, typeIndex);

mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
model->insertRow(model->rowCount(QModelIndex()));
mapper->toLast();
0
  • 25 июня 2018 г. 12:04

Подскажите как организовать в базе данных запись в поле таблицы типа result1 или result2 в зависимости от того, какой QRadioButton пользователь выбрал на форме. А также, чтобы при редактировании данных на форме включался нужный QRadioButton в зависимости от записи?

0
  • 25 июня 2018 г. 13:12
  • (ред.)
И если можно еще один вопрос.

Таблицы во вложении.


Если писать:

mainModel = new QSqlRelationalTableModel(this);
mainModel->setTable("menu");

mainModel->setSort(0, Qt::AscendingOrder);
mainModel->select();
ui->mainTableView->setModel(mainModel);

mainModel->setRelation(1, QSqlRelation("question", "id", "type"));
Все работает и данные на форме в таблице отображаются корректно.

А если вот так, то ничего не отображается вообще.

mainModel = new QSqlRelationalTableModel(this);
mainModel->setTable("menu");

mainModel->setSort(0, Qt::AscendingOrder);
mainModel->select();
ui->mainTableView->setModel(mainModel);

mainModel->setRelation(1, QSqlRelation("groups", "id", "Group name"));
Если убрать последнюю строку, то все отображается в таблице (без подстановки).

Поля id - not null, unique, auto inc, primary key.

Что может быть не так, где я туплю?

0

Имя поля таблицы  "Group name" меня смущает пробел. в нем. Просто никогда не использовал  и не видел пробелы в именах полей БД.

0

Добрый день!
Спасибо за ответ, но там было найдено решение, там одинаковые именя столбцов были в одном месте.

К сожалению 30-го июня был сбой и часть данных в базе данных сайта была утеряна.. То сообщение топикстартера мне не удалось восстановить...

0



Подскажите как организовать в базе данных запись в поле таблицы типа result1 или result2 в зависимости от того, какой QRadioButton пользователь выбрал на форме. А также, чтобы при редактировании данных на форме включался нужный QRadioButton в зависимости от записи?
Тут скорее все нужно уже больше полагаться на SQL. Т.е в зависимости от состояния QRadioButton делать запросы используя QSqlQuery.
Аналогично в зависимости от результатов запроса выставлять значения виджета.






0
Считывание реализовал так:

QSqlQuery query;
    query.prepare( "SELECT type FROM " + Table + " WHERE id = ?" );
    query.addBindValue(id);
    query.exec();

    while (query.next()) {
        if (query.value(0).toString() == "LOGO_HEADER") {
            ui->headLogoRButton->setChecked(true);
        }
        else {
            ui->mainLogoRButton->setChecked(true);
        }

Записывать:

mapper->submit();
model->submitAll();
QString value; if (ui->headLogoRButton->isChecked()) value = "LOGO_HEADER"; else value = "LOGO_MAIN"; query.prepare( "UPDATE " + Table + " SET type = ? WHERE id = ?" ); query.addBindValue(value); query.addBindValue(query.lastInsertId().toInt()); query.exec();











0
  • 3 июля 2018 г. 12:34

Большое спасибо всем за помощь!

0

Из опыта:  уменьшить время отладки на больших запросах я формирую строку с запросом которую можно скормить клиенту БД и проверяю запрос там. а потом уже использую в коде.

strSql=QString("SELECT a.TERMINAL_ID, t.name, a.SALEORDER_ID, a.NUM_CHECK, a.dat, a.sec, p.name, f.SHORTNAME, "
                   "a.GIVE, a.ORDERED, a.SUMMA, a.DISCOUNTSUMMA,a.GIVE1 "
                   "FROM SALEORDERS a "
                   "LEFT JOIN fuels f ON a.FUEL_ID=f.FUEL_ID "
                   "LEFT JOIN TERMINALS t ON a.TERMINAL_ID=t.TERMINAL_ID "
                   "LEFT JOIN PAYTYPES p ON p.PAYTYPE_ID=a.PAYTYPE_ID "
                   "where a.TERMINAL_ID=%1 and a.SHIFT_ID=%2 and a.NUM_CHECK=%3")
            .arg(ui->lineEditTerminalID->text().toInt())
            .arg(ui->lineEditShiftID->text().toInt())
            .arg(ui->lineEditNumCheck->text().toInt());
    modelSale->setQuery(strSql,dbc);

Для больших запросов очень полезно.
0

Спасибо. У меня в таблице всего 4 столбца, но на будущее возьму на вооружение :)

0

Такой вопрос. Никто случайно не писал свой класс для QComboBox для работы сполями бызы данных, а то через мапер выходит много однотипного кода. Хочется сократить.


Сейчас делаю так:


int typeIndex = model->fieldIndex("Security question");
model->setRelation(typeIndex, QSqlRelation("question", "id", "type"));
model->select();
QSqlTableModel *relModel = model->relationModel(typeIndex);
ui->sQuestionBox->setModel(relModel);
ui->sQuestionBox->setModelColumn(relModel->fieldIndex("type")); mapper->addMapping(ui->sQuestionBox, typeIndex);

0

Если код не имеет зависимости на какие-то внешние настройки, то можно просто наследоваться и настроить всё однотипное в конструкторе, если есть какие-то внешние параметры, то добавить публичный метод для настройки.

0

Не очень понял задачу?

0

Понял, спасибо. Единственные зависимости - имена таблиц и полей.

0

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
КА
19 февраля 2019 г. 18:32
Кристина Афанасьева

C++ - Тест 006. Перечисления

  • Результат:70баллов,
  • Очки рейтинга1
КА
19 февраля 2019 г. 18:26
Кристина Афанасьева

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:60баллов,
  • Очки рейтинга-1
КА
19 февраля 2019 г. 18:00
Кристина Афанасьева

C++ - Тест 002. Константы

  • Результат:50баллов,
  • Очки рейтинга-4
Последние комментарии
21 февраля 2019 г. 12:51
Евгений Легоцкой

Иногда CMake приходится перезапускать начисто, не обновляет кэш
R
21 февраля 2019 г. 12:29
RandyGallup

Я указал данные строки, т.к. без них у меня вылетала следующая ошибка: By not providing "FindQt5Core.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configurat...
21 февраля 2019 г. 12:08
BlinCT

Вот атк выглядит мой проектник, посмотрите его. cmake_minimum_required(VERSION 3.6)project(projecttimer)set(CMAKE_CXX_STANDARD 11)set(CMAKE_AUTOMOC ON)set(CMAKE_AUTORCC ON)find_packa...
21 февраля 2019 г. 12:04
BlinCT

Смотрите, если вы используете глобально для проекта -DCMAKE_PREFIX_PATH= то вам не надо уже указывать вот эти строкиset(Qt5Core_DIR "C:/Qt/5.12.1/mingw73_64/lib/cmake/Qt5Core")set(Qt5Gui_DIR...
R
21 февраля 2019 г. 11:54
RandyGallup

Даже не запускается. main.cpp у меня точно такой же, как в статье. CMakeLists.txt пришлось немного подправить (прикрепил ниже), т.к. не находились некоторые файлы. cmake_minimum_requi...
Сейчас обсуждают на форуме
21 февраля 2019 г. 8:58
Евгений Легоцкой

Ну у меня координаты передавались в зависимости от положения курсора мыши, а в вам по сути нужно будет аналогичным способом посылать даннные из полей ввода. Так что здесь скорее интерфес...
20 февраля 2019 г. 21:55
Евгений Легоцкой

Не до конца понимаю сути вопроса, наверное, нужно увидеть программный код и попытку его применения, но к методам базового класса можно обращаться в наследованном классе через вызов по имени ба...
MU
20 февраля 2019 г. 15:06
Maciej Urmański

Yes, ok I have solution! Thank you for directing me about annotate.:) Solution is: users_in = User.objects.filter(joined_users__goal=goal, joined_users__joined=True)
20 февраля 2019 г. 14:40
Евгений Легоцкой

Думаю, что ещё можно переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, который содержит модель и немного поиграться с индексом. Если это индекс, который соответству...
20 февраля 2019 г. 10:34
Евгений Легоцкой

Да, так тоже можно. Единственный момент в том, что lupdate не всегда понимает, к какому контексту это дело относится, и может запихать в левый контекст. В небольшом проекте это не критич...
Присоединяйтесь к нам в социальных сетях

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы