Evgenii Legotckoi
Evgenii LegotckoiТам. 14, 2015, 1:44 Т.Қ.

Qt/C++ - Сабақ 004. QSqlTableModel немесе Qt тілінде мәліметтер қорынан кестені қалай ұсынуға болады?

Мәліметтер қоры кестесіндегі ақпаратты көрсету үшін Qt құрылымы бірнеше класстарды пайдаланады:

  • QSqlQueryModel – өңделмеген SQL сұранысын көрсету арқылы кестені жасайтын модель. Бұл әсіресе күрделі сүзгілерді жасау және әртүрлі дерекқор кестелерінен ақпаратты құрастыру кезінде пайдалы болуы мүмкін. Бұл туралы толығырақ келесі сабақтарда.
  • QSqlTableModel - - бұл мақаладағы талқылау тақырыбы. Дерекқорда бар кестенің аты бойынша кестені жасайтын модель. Кемшіліктердің бірі идентификатор бойынша басқа кестелердегі өрістерге мәндерді ауыстыру үшін басқа кестелермен қарым-қатынастарды қосу әдістерінің жоқтығын атап өтуге болады.
  • QSqlRelationalTableModel - басқа кестелердегі жазбалардың идентификаторына сәйкес осы үлгі көрсететін кестенің мәндерін ауыстыра отырып, басқа кестелердің қатынастары бар кестені құруға мүмкіндік беретін класс.

Деректер базасында орналастырылған ақпаратпен ыңғайлы жұмыс істеу үшін қосымша сынып пайдаланылады, ол ішінара дизайн үлгісі болып табылады «Қасбет» .

Код Qt 5.4.1 негізінде QtCreator 3.3.1-де жазылған.

QSqlTableModel үшін жоба құрылымы

Жоба келесі файлдарды жасайтын Qt Widgets қолданбасы ретінде жасалған:

  • DataBase.pro - профиль;
  • mainwindow.h – қосымшаның негізгі терезесінің тақырып файлы;
  • mainwindow.cpp – терезенің бастапқы коды;
  • main.cpp – қолданба басталатын негізгі бастапқы файл;
  • mainwindow.ui – қосымшаның негізгі терезесінің формасы;
  • database.h – дерекқорда орналастырылған ақпаратпен жұмыс істеу үшін қолданылатын көмекші кластың тақырып файлы;
  • database.cpp – дерекқорда орналастырылған ақпаратпен жұмыс істеу үшін қолданылатын көмекші класстың бастапқы файлы;

Ескерту. Мен негізгі кодтың логикасын қажетсіз ақпаратпен шатастырмау үшін дизайнерде интерфейстің көп бөлігін жасаймын. Шындығында, бұл тек дәм мен әдетке байланысты мәселе .

mainwindow.ui

QSqlTableModel пішіні Біз графикалық интерфейстен tableView деп аталатын QTableView нысанын қолданатын сынақ қолданбасы үшін пішін жасаймыз.

DataBase.pro

Жоба профилінде SQL кітапханаларын пайдалануды жариялайтын директиваны қосу керек.

#-------------------------------------------------
#
# 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

Файл жобада пайдаланылады, әдепкі бойынша жасалады.

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

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

    return a.exec();
}

mainwindow.h

Бұл тақырып файлында QSqlTableModel және DataBase нысанының мәлімдемесі бар, дерекқорда орналастырылған ақпаратпен жұмыс істеу үшін қолданылатын көмекші сынып. Оларға қосымша біздің қолданбаның QSqlTableModel көрінісі мен үлгісін инициализациялау әдістері жарияланған.

#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

Деректерді көрсету үлгісімен барлық негізгі өзара әрекеттесу орын алатын бастапқы файл.

#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(); // Делаем выборку данных из таблицы
}

дерекқор.h

Дерекқормен өзара әрекеттесу мәселесін толық қараңғылықта қалдырмау үшін мен осы сыныптың тізімдерін түсініктемелермен ұсынамын. Жұмыс SQLite дерекқорымен орындалады, бірақ желілік қосылымды және әрбір нақты дерекқормен жұмыс істеудің нюанстарын қоспағанда, желілік деректер базасымен жұмыс істеу принципі ұқсас болады.

DataBase класының тақырып файлында әрі қарай жұмыс істеуге ыңғайлы болу үшін кесте атаулары мен кесте бағандарына арналған директиваларды көрсету керек. Сондай-ақ дерекқормен өзара әрекеттесу үшін қолданылатын әдістер, сонымен қатар қолданбаның жоғары деңгейлі қабаттарымен өзара әрекеттесу үшін интерфейстерді қамтамасыз ету.

#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

database.cpp

Дерекқорда орналастырылған ақпаратпен жұмыс істеу үшін пайдаланылатын көмекші сыныптың бастапқы файлы. Бұл жағдайда бағдарлама кодындағы сілтемелер санын азайту үшін бұл класста SQL сұраныстарының қалыптасуы максималды түрде жасырылады. Бастапқыда мұндай тәжірибе бастаушыға әртүрлі сыныптар мүмкіндігінше бір-бірінен бөлінген кодты дереу жазу мүмкіндігін қалыптастыруға көмектеседі, бұл OOP аспектілерінің бірі болып табылады.

#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;
}

Барлығы

Нәтиже негізгі қолданба терезесінің конструкторында дайындалған және енгізілген деректермен келесі пішіндегі кесте болуы керек.

QSqlTableModel көмегімен қолданбаның көрінісі

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

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

И
  • Сәуір 14, 2017, 10:51 Т.Ж.

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

И
  • Сәуір 14, 2017, 10:54 Т.Ж.

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

И
  • Сәуір 14, 2017, 11:10 Т.Ж.

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

Evgenii Legotckoi
  • Сәуір 14, 2017, 11:19 Т.Ж.

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

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

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

z
  • Мамыр 7, 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, 2017, 11:31 Т.Ж.

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

z
  • Мамыр 7, 2017, 12:23 Т.Қ.

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

Evgenii Legotckoi
  • Мамыр 7, 2017, 12:25 Т.Қ.

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

v
  • Сәуір 26, 2018, 6:20 Т.Қ.

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

v
  • Сәуір 26, 2018, 6:35 Т.Қ.

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

Evgenii Legotckoi
  • Сәуір 27, 2018, 3:39 Т.Ж.

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

v
  • Сәуір 27, 2018, 3:57 Т.Ж.

Да

Evgenii Legotckoi
  • Сәуір 27, 2018, 4:03 Т.Ж.

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

v
  • Сәуір 27, 2018, 4:06 Т.Ж.

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

v
  • Сәуір 27, 2018, 9:31 Т.Ж.

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

Evgenii Legotckoi
  • Сәуір 27, 2018, 9:33 Т.Ж.

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

v
  • Сәуір 27, 2018, 9:36 Т.Ж.

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

Evgenii Legotckoi
  • Сәуір 27, 2018, 9:38 Т.Ж.

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

B
  • Қаз. 8, 2018, 4:06 Т.Ж.

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

B
  • Қаз. 8, 2018, 4:07 Т.Ж.

Все понял

Evgenii Legotckoi
  • Қаз. 8, 2018, 4:07 Т.Ж.

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

B
  • Қаз. 8, 2018, 6: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, 2018, 6: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, 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, 2018, 10:27 Т.Ж.

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

Evgenii Legotckoi
  • Қаз. 8, 2018, 10:30 Т.Ж.

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

IscanderChe
  • Қаң. 15, 2019, 9:14 Т.Ж.

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

Evgenii Legotckoi
  • Қаң. 15, 2019, 9:17 Т.Ж.

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

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

IscanderChe
  • Қаң. 16, 2019, 2: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, 2019, 2:51 Т.Ж.
  • (өңделген)

потому, что нужно сохранять информацию для всех остальных ролей и столбцов через вызов переопределённого метода. Да к тому же вы ещё и зациклили вызов метода 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, 2019, 3:02 Т.Ж.

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

IscanderChe
  • Қаң. 16, 2019, 3:06 Т.Ж.

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

IscanderChe
  • Қаң. 16, 2019, 3:06 Т.Ж.

Спасибо!

IscanderChe
  • Қаң. 22, 2019, 6:11 Т.Ж.
  • (өңделген)

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

Evgenii Legotckoi
  • Қаң. 22, 2019, 6:50 Т.Ж.

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

IscanderChe
  • Қаң. 22, 2019, 7:09 Т.Ж.

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

Evgenii Legotckoi
  • Қаң. 22, 2019, 7:15 Т.Ж.
  • (өңделген)

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

IscanderChe
  • Қаң. 22, 2019, 8:13 Т.Ж.

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

Evgenii Legotckoi
  • Қаң. 22, 2019, 8:17 Т.Ж.
  • (өңделген)

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

a
  • Қаң. 14, 2020, 2:30 Т.Ж.

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

Evgenii Legotckoi
  • Қаң. 14, 2020, 2:33 Т.Ж.

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

a
  • Қаң. 14, 2020, 2:44 Т.Ж.

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

Evgenii Legotckoi
  • Қаң. 14, 2020, 2:50 Т.Ж.
  • (өңделген)

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

a
  • Қаң. 14, 2020, 5:29 Т.Ж.

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

Evgenii Legotckoi
  • Қаң. 14, 2020, 5:33 Т.Ж.

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

Т1
  • Мамыр 26, 2020, 7 Т.Ж.
  • (өңделген)

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

include "database.h"

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

Evgenii Legotckoi
  • Мамыр 26, 2020, 7:02 Т.Ж.

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

Т1
  • Мамыр 26, 2020, 7:22 Т.Ж.
  • (өңделген)

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

Т1
  • Мамыр 26, 2020, 7:23 Т.Ж.

Evgenii Legotckoi
  • Мамыр 26, 2020, 7:51 Т.Ж.

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

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

  • void DataBase::connectToDataBase()
  • bool DataBase::openDataBase()
Т1
  • Мамыр 26, 2020, 11:38 Т.Ж.

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

Т1
  • Мамыр 26, 2020, 11:55 Т.Ж.
  • (өңделген)

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

Evgenii Legotckoi
  • Мамыр 27, 2020, 2:51 Т.Ж.

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

VB
  • Қыр. 16, 2020, 5:57 Т.Ж.
  • (өңделген)

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

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, 2022, 4:30 Т.Ж.

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

IscanderChe
  • Сәуір 27, 2022, 9:43 Т.Ж.

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

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

d
  • Сәуір 28, 2022, 2:43 Т.Ж.

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

IscanderChe
  • Сәуір 28, 2022, 3:54 Т.Ж.

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

d
  • Сәуір 28, 2022, 9:16 Т.Ж.

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

IscanderChe
  • Сәуір 28, 2022, 9:36 Т.Ж.

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

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

АС
  • Там. 4, 2022, 5:33 Т.Ж.
  • (өңделген)

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

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

Пікірлер

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

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 Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

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