Evgenii Legotckoi
Evgenii Legotckoi14. August 2015 13:44

Qt/C++ - Lektion 004. QSqlTableModel – Wie präsentiert man die Tabelle aus der Datenbank?

Um die in einer Datenbanktabelle enthaltenen Informationen darzustellen, verwendet das Qt-Framework mehrere Klassen:

  • QSqlQueryModel - ein Modell, das eine Tabelle durch Angabe einer rohen SQL-Abfrage bildet. Es kann nützlich sein, wenn Sie besonders anspruchsvolle Filter erstellen und Informationen aus verschiedenen Datenbanktabellen zusammenstellen. Mehr dazu in den folgenden Lektionen.
  • QSqlTableModel - das Thema unseres Gesprächs in diesem Artikel. Ein Modell, das eine Tabelle mit dem Namen der Tabelle bildet, die in der Datenbank vorhanden ist. Von den Minuspunkten können wir das Fehlen von Methoden zum Verbinden von Links mit anderen Tabellen feststellen, um Werte in Feldern aus anderen Tabellen nach ID zu ersetzen.
  • QSqlRelationalTableModel - eine Klasse, die es Ihnen ermöglicht, eine Tabelle mit Links aus anderen Tabellen zu bilden und die Werte der Tabelle, die dieses Modell darstellt, gemäß den IDs der in anderen Tabellen enthaltenen Datensätze zu ersetzen.

Für komfortables Arbeiten mit Informationen, die in die Datenbank gestellt werden, wird eine zusätzliche Klasse verwendet, die teilweise ein Gestaltungsmuster "Fassade" ist.

Der Programmcode wurde in QtCreator 3.3.1 basierend auf Qt 5.4.1 geschrieben.

Projektstruktur für QSqlTableModel

Das Projekt wird als Qt-Widgets-Anwendung erstellt, in der die folgenden Dateien erstellt werden:

  • DataBase.pro - Profil;
  • mainwindow.h - Header-Datei des Hauptanwendungsfensters;
  • mainwindow.cpp - Fensterquellcode;
  • main.cpp - die Hauptquelldatei, von der aus die Anwendung startet;
  • mainwindow.ui - Form des Hauptanwendungsfensters;
  • database.h - Header-Datei der Hilfsklasse, die verwendet wird, um mit Informationen zu arbeiten, die in der Datenbank platziert sind;
  • database.cpp - die Quelldatei der Hilfsklasse, die verwendet wird, um mit Informationen zu arbeiten, die in der Datenbank platziert sind;

Notiz. Ich erstelle den größten Teil der Benutzeroberfläche im Designer, um die Logik des Hauptcodes nicht mit unnötigen Informationen zu überladen. Tatsächlich ist dies nur eine Frage des Geschmacks und der Gewohnheit.

mainwindow.ui

Formular für QSqlTableModel Erstellen Sie ein Formular für die Testanwendung, das ein QTableView Objekt namens tableView von der GUI verwendet.

DataBase.pro

Dem Projektprofil muss eine Direktive hinzugefügt werden, die die Verwendung von SQL-Bibliotheken deklariert.

#-------------------------------------------------
#
# Project created by QtCreator 2015-08-10T16:08:24
#
#-------------------------------------------------

QT       += core
QT       += gui
QT       += sql

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = DataBase
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp \
    database.cpp

HEADERS  += mainwindow.h \
    database.h

FORMS    += mainwindow.ui

main.cpp

Die Datei wird im Projekt verwendet und wird standardmäßig erstellt.

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

Diese Header-Datei enthält die Deklaration des QSqlTableModel und DataBase Objekts, einer Hilfsklasse, die verwendet wird, um mit Informationen zu arbeiten, die in der Datenbank platziert werden. Darüber hinaus werden Methoden zur Initialisierung des Erscheinungsbilds und des Modells QSqlTableModel unserer Anwendung deklariert.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlTableModel>
/* Подключаем заголовочный файл для работы с информацией, которая помещена в базу данных */
#include "database.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow  *ui;
    /* В проекте используются объекты для взаимодействия с информацией в базе данных
     * и моделью представления таблицы базы данных
     * */
    DataBase        *db;
    QSqlTableModel  *model;

private:
    /* Также присутствуют два метода, которые формируют модель
     * и внешний вид TableView
     * */
    void setupModel(const QString &tableName, const QStringList &headers);
    void createUI();
};

#endif // MAINWINDOW_H

mainwindow.cpp

Die Quelldatei, in der alle Hauptaktionen für die Interaktion mit dem Datenpräsentationsmodell stattfinden.

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    /* Первым делом необходимо создать объект, который будет использоваться для работы с данными нашей БД
     * и инициализировать подключение к базе данных
     * */
    db = new DataBase();
    db->connectToDataBase();

    /* После чего производим наполнение таблицы базы данных
     * контентом, который будет отображаться в TableView
     * */
    for(int i = 0; i < 4; i++){
        QVariantList data;
        int random = qrand(); // Получаем случайные целые числа для вставки а базу данных
        data.append(QDate::currentDate()); // Получаем текущую дату для вставки в БД
        data.append(QTime::currentTime()); // Получаем текущее время для вставки в БД
        // Подготавливаем полученное случайное число для вставки в БД
        data.append(random);           
        // Подготавливаем сообщение для вставки в базу данных
        data.append("Получено сообщение от " + QString::number(random)); 
        // Вставляем данные в БД
        db->inserIntoTable(data);
    }

    /* Инициализируем модель для представления данных
     * с заданием названий колонок
     * */
    this->setupModel(TABLE,
                     QStringList() << trUtf8("id")
                                   << trUtf8("Дата")
                                   << trUtf8("Время")
                                   << trUtf8("Рандомное число")
                                   << trUtf8("Сообщение")
               );

    /* Инициализируем внешний вид таблицы с данными
     * */
    this->createUI();
}

MainWindow::~MainWindow()
{
    delete ui;
}

/* Метод для инициализации модеи представления данных
 * */
void MainWindow::setupModel(const QString &tableName, const QStringList &headers)
{
    /* Производим инициализацию модели представления данных
     * с установкой имени таблицы в базе данных, по которому
     * будет производится обращение в таблице
     * */
    model = new QSqlTableModel(this);
    model->setTable(tableName);

    /* Устанавливаем названия колонок в таблице с сортировкой данных
     * */
    for(int i = 0, j = 0; i < model->columnCount(); i++, j++){
        model->setHeaderData(i,Qt::Horizontal,headers[j]);
    }
    // Устанавливаем сортировку по возрастанию данных по нулевой колонке
    model->setSort(0,Qt::AscendingOrder);
}

void MainWindow::createUI()
{
    ui->tableView->setModel(model);     // Устанавливаем модель на TableView
    ui->tableView->setColumnHidden(0, true);    // Скрываем колонку с id записей
    // Разрешаем выделение строк
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    // Устанавливаем режим выделения лишь одно строки в таблице
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    // Устанавливаем размер колонок по содержимому
    ui->tableView->resizeColumnsToContents();
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableView->horizontalHeader()->setStretchLastSection(true);

    model->select(); // Делаем выборку данных из таблицы
}

database.h

Um die Frage der Interaktion mit der Datenbank nicht im Dunkeln zu lassen, versorge ich Listings dieser Klasse auch mit Kommentaren. Die Arbeit wird mit der SQLite-Datenbank erledigt, aber das Prinzip der Arbeit mit Netzwerkdatenbanken ist dasselbe, mit Ausnahme der Netzwerkverbindung und der Nuancen der Arbeit mit jeder spezifischen Datenbank.

In der Header-Datei der DataBase -Klasse ist es für die weitere Arbeit erforderlich, Direktiven für die Namen der Tabelle und der Tabellenspalten anzugeben. Und auch die Methoden, die verwendet werden, um mit der Datenbank zu interagieren, sowie Schnittstellen für diese Interaktion mit übergeordneten Schichten der Anwendung bereitzustellen.

#ifndef DATABASE_H
#define DATABASE_H

#include <QObject>
#include <QSql>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlDatabase>
#include <QFile>
#include <QDate>
#include <QDebug>

/* Директивы имен таблицы, полей таблицы и базы данных */
#define DATABASE_HOSTNAME   "ExampleDataBase"
#define DATABASE_NAME       "DataBase.db"

#define TABLE                   "TableExample"
#define TABLE_DATE              "Date"
#define TABLE_TIME              "Time"
#define TABLE_MESSAGE           "Message"
#define TABLE_RANDOM            "Random"

class DataBase : public QObject
{
    Q_OBJECT
public:
    explicit DataBase(QObject *parent = 0);
    ~DataBase();
    /* Методы для непосредственной работы с классом
     * Подключение к базе данных и вставка записей в таблицу
     * */
    void connectToDataBase();
    bool inserIntoTable(const QVariantList &data);

private:
    // Сам объект базы данных, с которым будет производиться работа
    QSqlDatabase    db;

private:
    /* Внутренние методы для работы с базой данных
     * */
    bool openDataBase();
    bool restoreDataBase();
    void closeDataBase();
    bool createTable();
};

#endif // DATABASE_H

datenbank.cpp

Die Quelldatei für eine Hilfsklasse, die verwendet wird, um mit Informationen zu arbeiten, die in der Datenbank platziert werden. In diesem Fall wird die Bildung von SQL-Abfragen in dieser Klasse maximal ausgeblendet, um die Anzahl der Verknüpfungen im Programmcode zu reduzieren. Eine solche Praxis am Anfang kann einem Anfänger helfen, sofort Code zu schreiben, in dem verschiedene Klassen so weit wie möglich voneinander isoliert sind, was einer der Aspekte von OOP ist.

#include "database.h"

DataBase::DataBase(QObject *parent) : QObject(parent)
{

}

DataBase::~DataBase()
{

}

/* Методы для подключения к базе данных
 * */
void DataBase::connectToDataBase()
{
    /* Перед подключением к базе данных производим проверку на её существование.
     * В зависимости от результата производим открытие базы данных или её восстановление
     * */
    if(!QFile("C:/example/" DATABASE_NAME).exists()){
        this->restoreDataBase();
    } else {
        this->openDataBase();
    }
}

/* Методы восстановления базы данных
 * */
bool DataBase::restoreDataBase()
{
    if(this->openDataBase()){
        if(!this->createTable()){
            return false;
        } else {
            return true;
        }
    } else {
        qDebug() << "Не удалось восстановить базу данных";
        return false;
    }
    return false;
}

/* Метод для открытия базы данных
 * */
bool DataBase::openDataBase()
{
    /* База данных открывается по заданному пути
     * и имени базы данных, если она существует
     * */
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setHostName(DATABASE_HOSTNAME);
    db.setDatabaseName("C:/example/" DATABASE_NAME);
    if(db.open()){
        return true;
    } else {
        return false;
    }
}

/* Методы закрытия базы данных
 * */
void DataBase::closeDataBase()
{
    db.close();
}

/* Метод для создания таблицы в базе данных
 * */
bool DataBase::createTable()
{
    /* В данном случае используется формирование сырого SQL-запроса
     * с последующим его выполнением.
     * */
    QSqlQuery query;
    if(!query.exec( "CREATE TABLE " TABLE " ("
                            "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                            TABLE_DATE      " DATE            NOT NULL,"
                            TABLE_TIME      " TIME            NOT NULL,"
                            TABLE_RANDOM    " INTEGER         NOT NULL,"
                            TABLE_MESSAGE   " VARCHAR(255)    NOT NULL"
                        " )"
                    )){
        qDebug() << "DataBase: error of create " << TABLE;
        qDebug() << query.lastError().text();
        return false;
    } else {
        return true;
    }
    return false;
}

/* Метод для вставки записи в базу данных
 * */
bool DataBase::inserIntoTable(const QVariantList &data)
{
    /* Запрос SQL формируется из QVariantList,
     * в который передаются данные для вставки в таблицу.
     * */
    QSqlQuery query;
    /* В начале SQL запрос формируется с ключами,
     * которые потом связываются методом bindValue
     * для подстановки данных из QVariantList
     * */
    query.prepare("INSERT INTO " TABLE " ( " TABLE_DATE ", "
                                             TABLE_TIME ", "
                                             TABLE_RANDOM ", "
                                             TABLE_MESSAGE " ) "
                  "VALUES (:Date, :Time, :Random, :Message )");
    query.bindValue(":Date",        data[0].toDate());
    query.bindValue(":Time",        data[1].toTime());
    query.bindValue(":Random",      data[2].toInt());
    query.bindValue(":Message",     data[3].toString());
    // После чего выполняется запросом методом exec()
    if(!query.exec()){
        qDebug() << "error insert into " << TABLE;
        qDebug() << query.lastError().text();
        return false;
    } else {
        return true;
    }
    return false;
}

Ergebnis

Als Ergebnis sollten Sie eine Platte der folgenden Form mit den Daten erhalten, die vorbereitet und in den Konstruktor des Hauptanwendungsfensters eingefügt wurden.

Anwendungsdarstellung mit QSqlTableModel

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

И
  • 14. April 2017 10:51

Здравствуйте, а, скажите, сам объект QSqlTableModel предоставляет доступ к данным, которые уже есть в таблице? Например, получить в какую - то переменную ранее записанное рандомное число из строки с индексом n?Или, это только возможно запросом

И
  • 14. April 2017 10:54

Метод setData(строка, столбец, значение) есть, а, метода, например, типа, getData(строка, столбец), не нашел

И
  • 14. April 2017 11:10

Разобрался QSqlRecord rec = model(номер строки) - получаем строку int num = rec.value("TABLE_RANDOM"); - получаем поле

Всё гораздо проще, метод, который Вы искали называется не getData() , а просто data() . Для получения данных нужно дернуть QModelIndex из модели. Выглядеть это будет так:

model->data(model->index(0, 2)); 
// 0 - номер строки
// 2 - номер колонки

Метод вернёт QVariant , который будет содержать данные.

z
  • 7. Mai 2017 10:43

А у меня выхлоп: Не удалось восстановить базу данных QSqlQuery::prepare: database not open error insert into TableExample "No query Unable to fetch row" QSqlQuery::prepare: database not open error insert into TableExample "No query Unable to fetch row" QSqlQuery::prepare: database not open error insert into TableExample "No query Unable to fetch row" QSqlQuery::prepare: database not open error insert into TableExample "No query Unable to fetch row" QSqlQuery::prepare: database not open error insert into TableExample "No query Unable to fetch row" QSqlDatabasePrivate::database: unable to open database: "out of memory Error opening database"

Evgenii Legotckoi
  • 7. Mai 2017 11:31

В методах connectToDataBase и openToDataBase пропишите свой путь к базе данных.

z
  • 7. Mai 2017 12:23

Тоесть надо создать пустую базу sqlite сторонним ПО?

Evgenii Legotckoi
  • 7. Mai 2017 12:25

Нет. нужно указать корректный пути к базе данных. Если вы скопипастили код, то скорее всего у вас нет директории example на диске C, поэтому и не фурычит.

v
  • 26. April 2018 18:20

Здравствуйте, очень понравился Ваш урок. Сначала решил взять идею - не получилось, причем ошибки странные. После этого решил взять Ваш код и выяснилось, что ошибки остаются теми же. Компилятор ругается на то, что вроде как конструктор и деструктор класса DataBase должны быть виртуальными...Плохое решение проблемы, но все же отчасти ее решение - это убрать макрос Q_Object в заголовочном файле DataBase. При таком решении проблемы выскакивает ошибка " ASSERT: "!isEmpty()" in file ....." и программа сворачивается. Пожалуйста, подскажите в чем загвоздка, почему так и как это все исправить? Есть предположение, что это связано с настройкой компилятора, но...не знаю.

v
  • 26. April 2018 18:35

К посту выше...Проблема "виртуальных" конструктора и деструктора решается с помощью перезапуска qmake (его вообще нужно всегда перезапускать, если добавляешь макрос Q_Object в свой класс). Но вторая проблема, к сожалению осталась актуальной((  "ASSERT: "!isEmpty()" in file C:/Users/qt/work/qt/qtbase/src/corelib/tools/qlist.h, line 345 "

Evgenii Legotckoi
  • 27. April 2018 03:39

Добрый день! В методе connectToDataBase вы прописали свой путь к базе данных?

v
  • 27. April 2018 03:57

Да

Evgenii Legotckoi
  • 27. April 2018 04:03

Сейчас сразу и не припомню, было ли нечто такое, может в новых версиях Qt что-то поменяли, что генерирует ошибку. После работы гляну, какая там может быть проблема.

v
  • 27. April 2018 04:06

Хорошо, спасибо большое! Очень жду Вашего ответа. Я тоже пока попробую разобраться и может реализовать как-нибудь по-другому.

v
  • 27. April 2018 09:31

У меня все заработало. Не могу точно сказать в чем была причина, есть только догадки. Но программа заработала только после того, как я удалил базу данных с таким же названием, которая была создана мною вручную. Наверное, это мешало корректной работе программы, но не совсем ясно почему...ведь мы всего лишь обращаемся к этой БД с запросами и все.

Evgenii Legotckoi
  • 27. April 2018 09:33

Скорее всего дело в метаинформации, которой не было при создании файла вручную. При подключении некорректный файл крашил программу...

v
  • 27. April 2018 09:36

Да, спасибо Вам большое! У Вас очень интересные уроки!!!

Evgenii Legotckoi
  • 27. April 2018 09:38

Спасибо за отзыв. Будут вопросы не по статьям, то не стесняйтесь задавать их на форуме сайта .

B
  • 8. Oktober 2018 04:06

DataBase is unknown type. Подскажите, в чем проблема, вроде все заголовочные подключаю

B
  • 8. Oktober 2018 04:07

Все понял

Evgenii Legotckoi
  • 8. Oktober 2018 04:07

ММм.. хорошо, А что там не так было?

B
  • 8. Oktober 2018 06:41

Я не подключил header класса, поэтому он не знал тип такой. Подскажите пожалуйста

Я qDebug()`ом вызываю значения, которые подаю в базу данных, как я понимаю, база ругается на QDate и QTime


QDate("2018-10-08")

QTime("13:37:04.454")

26500

"Получено сообщение от 26500"

error insert into TableExample

" Parameter count mismatch"

Evgenii Legotckoi
  • 8. Oktober 2018 06:49

Наверное у вас базад данных не создалась, поправьте путь к место, где должна создаться база данных вот в этом методе

bool DataBase::openDataBase()
{
    /* База данных открывается по заданному пути
     * и имени базы данных, если она существует
     * */
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setHostName(DATABASE_HOSTNAME);
    db.setDatabaseName("C:/example/" DATABASE_NAME);
    if(db.open()){
        return true;
    } else {
        return false;
    }
}


B
  • 8. Oktober 2018 10:21
bool DataBase::openDataBase()
{
    db = QSqlDatabase::addDatabase("QSQLITE");

    db.setHostName(DATABASE_HOSTNAME);
    db.setDatabaseName("C:/Users/esmit/Documents/Qt/DataBase/" DATABASE_NAME);

    if(db.open())
        return true;
    else
        return false;
}


B
  • 8. Oktober 2018 10:27

В отладчике возвращает true, проблема не в этом

Evgenii Legotckoi
  • 8. Oktober 2018 10:30

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

IscanderChe
  • 15. Januar 2019 09:14

Спасибо за урок!
Вопрос: что нужно сделать, чтобы в tableView показывалось, например, 12:56, а не 12:56:34.554?

Evgenii Legotckoi
  • 15. Januar 2019 09:17

Наследоваться от QSqlTableModel и переопределить метод data для Qt::DisplayRole. Там сделать необходимые проебразования формата.

И потом уже использовать переопределённую модель вместо QSqlTableModel

IscanderChe
  • 16. Januar 2019 02:43

Сделал вот так. В tableView ничего нет, кроме заголовка.

QVariant MySqlTableModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DisplayRole)
    {
        QTime time = this->data(index, Qt::DisplayRole).toTime();
        QString str = time.toString("hh:mm:ss");
        return str;
    }
    else
        return QVariant();
}
Evgenii Legotckoi
  • 16. Januar 2019 02:51
  • (bearbeitet)

потому, что нужно сохранять информацию для всех остальных ролей и столбцов через вызов переопределённого метода. Да к тому же вы ещё и зациклили вызов метода data.

QVariant MySqlTableModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DisplayRole)
    {
        QTime time = QSqlTableModel::data(index, Qt::DisplayRole).toTime();
        QString str = time.toString("hh:mm:ss");
        return str;
    }

    return QSqlTableModel::data(index, role);
}
IscanderChe
  • 16. Januar 2019 03:02

Всё равно пусто, хотя строка с данными в базу добавляется.

IscanderChe
  • 16. Januar 2019 03:06

Заработало. Забыл model->select(); вписать.

IscanderChe
  • 16. Januar 2019 03:06

Спасибо!

IscanderChe
  • 22. Januar 2019 06:11
  • (bearbeitet)

Ещё небольшой вопрос.
Я добился, чтобы в tableView в колонке flag показывался чекбокс (через флаг Qt::ItemIsUserCheckable) и управлял содержимым базы . Как теперь убрать цифру из поля, чтобы остался только чекбокс?
flag.JPG flag.JPG

Evgenii Legotckoi
  • 22. Januar 2019 06:50

Переопределить метод data для той колонки и роли Qt::DisplayRole, чтобы в том случае возвращался QVariant() я так думаю...
Но возможно, что у вас там будут нюансы, если вы туда чекбокс запихали

IscanderChe
  • 22. Januar 2019 07:09

Получилось приемлемо. Спасибо!
Нюанс только в том, что поле рядом с чекбоксом не пропадает, оно просто пустое, что видно при выделении ячейки. Но этого достаточно.

Evgenii Legotckoi
  • 22. Januar 2019 07:15
  • (bearbeitet)

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

IscanderChe
  • 22. Januar 2019 08:13

Не проще тогда использовать сразу кастомный делегат с чекбоксом? Я попробовал, но там засада в том, что чекбокс показывается только при щелчке на ячейку, а дефолтно показывается значение. Как эту засаду обойти, я не смог придумать, плохо ещё ориентируюсь в моделях.

Evgenii Legotckoi
  • 22. Januar 2019 08:17
  • (bearbeitet)

Создайте тогда тему здесь на форуме в разделе Qt с выкладками кода и вашими попытками внедрения делегата, позже гляну или может кто-то ещё глянет из опытных пользователей.

a
  • 14. Januar 2020 02:30

Всем привет. Возник вопрос, можно ли работать с QtSql без сырых sql запросов, как в различный orm, через классы qsqltablemodel, qsqlrelationtablemodel?

Evgenii Legotckoi
  • 14. Januar 2020 02:33

Добрый день. В Qt нет ORM в QtSql, а классы qsqltablemodel и qsqlrelationtablemodel дают относительно слабый функционал, даже для использования фильтрации потребуется писать кусок SQL запроса. Без сырых запросов не обойдётесь.

a
  • 14. Januar 2020 02:44

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

Evgenii Legotckoi
  • 14. Januar 2020 02:50
  • (bearbeitet)

Вы заблуждаетесь. Любая нормальная ORM позволяет выполнение сырых SQL запросов. А если хорошо разобраться в работе моделей данных в Qt, то не составит труда использовать ORM вместе с Qt, ту же самую ORM Wt::Dbo. Нет особой гибкости в том, что приходится тратить уйму времени на написание сырых запросов, когда ORM позволяет всё это выполнять значительно быстрее. Я думаю, что со стороны Qt Company - это является недоработкой, что они не попытались сделать свою ORM, ресурсы им сейчас это позволяют. Так что действительно жаль, что этого нет из коробки.

a
  • 14. Januar 2020 05:29

Спасибо за инфу. Поиск качественной ORM привел меня только к sqlite_orm, но не подходит из-за необходимости полноценной поддержки c++14. Про framework Wt не слышал, спасибо за наводку.

Evgenii Legotckoi
  • 14. Januar 2020 05:33

Рекомендую Wt, достаточно мощная вещь. Этот фреймворк может использоваться для написания сайтов на C++, либо можно использовать только отдельный компоненты, например только ORM. Но я не знаю, какая требуется минимальная версия стандарта C++ для него. А также он требует boost библиотеку. У нас в проекте используется boost, а также C++17. Поэтому никогда не задумывался о минимальных требованиях к этому фреймворку.

Т1
  • 26. Mai 2020 07:00
  • (bearbeitet)

не удается подключиить библеотеку

include "database.h"

выдает ошибку. Можете помочь?

Evgenii Legotckoi
  • 26. Mai 2020 07:02

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

Т1
  • 26. Mai 2020 07:22
  • (bearbeitet)

полностью повторил структору проекта. В форму дабавил tableView. Но при запуске получаю форму только с пустым tableView. Можете подсказать в чем пробелма?

Т1
  • 26. Mai 2020 07:23

Evgenii Legotckoi
  • 26. Mai 2020 07:51

У вас база данных не открылась

Исправьте путь к базе данных на свой корректный в следующих методах

  • void DataBase::connectToDataBase()
  • bool DataBase::openDataBase()
Т1
  • 26. Mai 2020 11:38

спасибо, все сработало

Т1
  • 26. Mai 2020 11:55
  • (bearbeitet)

Подскажите пожалуйста как изменить данные в базе, тип столбцов и сделать столбцы шире

Evgenii Legotckoi
  • 27. Mai 2020 02:51

Напишите метод с SQL запросом, который изменит данные или их тип. Это ALTER методы для изменения типа данных, а также INSERT и UPDATE методы для добавления и обновления данных. Это вы можете найти в документации на SQL. Просто напишите QSqlQuery запросы, как это показано в методе inserIntoTable
Что касается ширины столбцов, то QTableView имеет метод setColumnWidth

VB
  • 16. September 2020 05:57
  • (bearbeitet)

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

bool Model::update_in_db(Data *item)
{
    QSqlQuery query;
    query.setForwardOnly(true);
    query.prepare("UPDATE myDB SET      \n"
                  " code_all = :code,                     \n"
                  " date = :date,                                \n"
                  " person = :person,                        \n"
                  "WHERE id = :id;                                \n"
                  );

    query.bindValue(":code", item->Code_all());
    query.bindValue(":date", item->Date());
    query.bindValue(":person", item->Person());

    if(query.exec()) {
        return true;
    } else {
        qCritical() << query.lastError().databaseText();
        qCritical() << query.lastError().driverText();
        qCritical() << query.lastError().nativeErrorCode();

        return false;
    }
}

А также для удаления такой метод не обновляет базу данных SQLite (модель унаследована от QSqlTableModel):

Model::delete_from_db()
{
    QSqlQuery query;
    query.setForwardOnly(true);
        query.prepare("DELETE FROM myDB WHERE id = :ID ;");
        query.bindValue(":ID", currentIndex.row());

        if(!query.exec()){
            qCritical() << query.lastError().databaseText().toUtf8().data();
            qCritical() << query.lastError().driverText();
            qCritical() << query.lastError().nativeErrorCode();
            return false;
        } else {
            return true;
        }
        return false;
}
d
  • 27. April 2022 04:30

Не могу понять как связывается БД и модель. Подскажите, пожалуйста.

IscanderChe
  • 27. April 2022 09:43

model = new QSqlTableModel(this);
model->setTable(tableName);

Это строки 61-62 в mainwindow.cpp

d
  • 28. April 2022 02:43

IscanderChe. Мы создаем объект класс DataBase. Как этот объект связать с объектом класса QSqlTableMode?

IscanderChe
  • 28. April 2022 03:54

QSqlTableModel(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase())

d
  • 28. April 2022 09:16

Мой вопрос был про объект класса DataBase. Как он связывается с объектом класса QSqlTableModel.Можете указать строчку в коде?

IscanderChe
  • 28. April 2022 09:36

Объект QSqlDatabase() устанавливается глобально, для всего кода. DataBase, соответственно, делает то же самое, только с помощью своих методов, которые используются в mainwindow.cpp, а сам объект подключается и объявляется в mainwindow.h. Затем через таблицы из БД происходит связь с моделью. Это про первый мой ответ.

Если вы, к примеру, открываете несколько баз данных в одном приложении, то вы можете указать при создании модели, какую именно базу данных использовать. Это про мой второй ответ вам.

АС
  • 4. August 2022 05:33
  • (bearbeitet)

error insert into TableExample
" Количество параметров не совпадает"

Я путь свой прописывала и даже бд удаляла, чтобы заново сделать, не работает. (всё остальное как у вас... Вроде как. Хотя я так и не увидела, где используется closeDataBase())

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken