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

Qt/C++ - Урок 006. QSqlQueryModel - Таблицы в Qt с помощью SQL-запросов

QSqlQueryModel, qsqlquerymodel example, qt, qt таблицы, query

Использование QSqlQueryModel для формирования таблиц в Qt является наиболее хардкорным вариантом с наиболее низким уровнем абстракции, чем использование QSqlTableModel или QSqlRelationalTableModel . Но при всём при этом и наиболее гибкий вариант, который требует более глубокого знания языка SQL-запросов. В предыдущей статье были построены две таблицы:

  • Основная , в которой были колонки Дата, Время, Имя Хоста, IP-адрес.
  • Таблица устройств, в которой были колонки Имя Хоста и IP-адрес.

В Основной таблице в колонках Имени Хоста и IP-адреса указывались ID-устройств, по которым проводилась подстановка данных из Таблицы устройств. В данной статье структура первой таблицы и следовательно таблицы будут выглядеть иначе:

  • Основная , в которой были колонки Дата, Время, ID устройства.
  • Таблица устройств, в которой были колонки Имя Хоста и IP-адрес.

Генерация Основной таблицы в Приложении будет производиться SQL-запросом и таблица будет иметь соответственно колонки Дата, Время, Имя Хоста и IP-адрес.

Структура проекта для QSqlQueryModel

Структура проекта QSqlQueryModel остается такой же, как в предыдущей статье .

mainwindow.ui

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

  • tableView
  • tableViewDevice

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

В данном файле подключается библиотека QSqlQueryModel , тогда как классы QSqlRelationalTableModel , QSqlRelationalDelegate и QSqlRelation не будут использоваться. Также изменяется сигнатура методов инициализации моделей, поскольку для объекта QSqlQueryModel нет метода по установке имени таблицы, к которой будет обращаться данный объект.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlQueryModel>

/* Подключаем заголовочный файл для работы с базой данных */
#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;
    QSqlQueryModel              *modelMain;
    QSqlQueryModel              *modelDevice;

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

#endif // MAINWINDOW_H

mainwindow.cpp

Главное отличие кода в этом исходном файле от кода из предыдущей статьи заключается в том, что в методах для инициализации моделей используется SQL-запрос, которые выполняется методом setQuery() .

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("QSqlQueryModel Example");
    /* Первым делом необходимо создать объект для работы с базой данных
     * и инициализировать подключение к базе данных
     * */
    db = new DataBase();
    db->connectToDataBase();

    /* После чего производим наполнение таблицы базы данных
     * контентом, который будет отображаться в tableView и tableViewDevice
     * */
    for(int i = 1; i < 4; i++){
        QVariantList data;
        data.append("Device " + QString::number(i));
        data.append("172.168.13." + QString::number(i));
        db->inserIntoDeviceTable(data);
    }

    for(int i = 0; i < 10; i++){
        QVariantList data;
        QString random = QString::number(qrand() % ((4 + 1) - 1) + 1);
        data.append(QDate::currentDate());
        data.append(QTime::currentTime());
        data.append(random);
        db->inserIntoMainTable(data);
    }

    /* Инициализируем модели для представления данных
     * с заданием названий колонок
     * */
    this->setupMainModel(QStringList() << trUtf8("id")
                                       << trUtf8("Дата")
                                       << trUtf8("Время")
                                       << trUtf8("Имя хоста")
                                       << trUtf8("IP адрес")
               );

    this->setupDeviceModel(QStringList() << trUtf8("id")
                                         << trUtf8("Имя хоста")
                                         << trUtf8("IP адрес")
               );
    /* Инициализируем внешний вид таблицы с данными
     * */
    this->createUI();
}

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

/* Метод для инициализации модели представления данных
 * */
void MainWindow::setupMainModel(const QStringList &headers)
{
    /* Производим инициализацию модели представления данных
     * */
    modelMain = new QSqlQueryModel(this);

    modelMain->setQuery("SELECT "
                        TABLE ".id, "
                        TABLE "." TABLE_DATE ", "
                        TABLE "." TABLE_TIME ", "
                        DEVICE "." DEVICE_HOSTNAME ", "
                        DEVICE "." DEVICE_IP
                        " FROM " TABLE ", " DEVICE
                        " WHERE " DEVICE ".id = " TABLE "." TABLE_DEVICE_ID
                        " ORDER BY " TABLE "." TABLE_DATE " DESC , " TABLE "." TABLE_TIME " DESC"
                        );

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

void MainWindow::setupDeviceModel(const QStringList &headers)
{
    /* Производим инициализацию модели представления данных
     * */
    modelDevice = new QSqlQueryModel(this);

    modelDevice->setQuery("SELECT "
                        DEVICE ".id, "
                        DEVICE "." DEVICE_HOSTNAME ", "
                        DEVICE "." DEVICE_IP
                        " FROM " DEVICE
                        );
    /* Устанавливаем названия колонок в таблице с сортировкой данных
     * */
    for(int i = 0, j = 0; i < modelDevice->columnCount(); i++, j++){
        modelDevice->setHeaderData(i,Qt::Horizontal,headers[j]);
    }
}

void MainWindow::createUI()
{
    ui->tableView->setModel(modelMain);     // Устанавливаем модель на 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);

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

Для того, чтобы обновить данные в таблице, необходимо повторить SQL-запрос. Это делается вызовом метода модели query() , у которого применяется метод lastQuery() , как показано в коде ниже:

model->setQuery(modelDevice->query().lastQuery());

database.h

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

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

#define TABLE                   "MainTable"
#define TABLE_DATE              "Date"
#define TABLE_TIME              "Time"
#define TABLE_DEVICE_ID         "DeviceID"

#define DEVICE                  "DeviceTable"
#define DEVICE_IP               "IP"
#define DEVICE_HOSTNAME         "Hostname"

database.cpp

В данном файле изменению подвергаются лишь два метода, которые работают с Основной таблицей . Из-за того, что изменилось число колонок, которые применены в данной таблице.

/* Метод для создания основной таблицы в базе данных
 * */
bool DataBase::createMainTable()
{
    /* В данном случае используется формирование сырого 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_DEVICE_ID " INTEGER         NOT NULL"
                        " )"
                    )){
        qDebug() << "DataBase: error of create " << TABLE;
        qDebug() << query.lastError().text();
        return false;
    } else {
        return true;
    }
    return false;
}

***

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

Итог

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

Какаим образом можно вставить в базу даннных сразу несколько строк? Ситуация такая - на COM-порт приходят данные, непрерывно и поступают в парсер. Там, после обработки записываются в QVariantList (как в примере и далее в БД), но из-за того, что данные идут непрерывно, база данных постоянно занята и обратиться к ней невозможно, пока не отключен порт. Какаим образом в QVariantList можно записать сразу несколько строк, а потом все их отправить в БД?

Тут скорее нужно правильно написать сырой запрос и использовать QSqlQuery

Например, если есть несколько инсертов

INSERT INTO MyTable VALUES ("John", 123, "Lloyds Office");
INSERT INTO MyTable VALUES ("Jane", 124, "Lloyds Office");
INSERT INTO MyTable VALUES ("Billy", 125, "London Office");
INSERT INTO MyTable VALUES ("Miranda", 126, "Bristol Office");

То нужно написать соответсвующий запрос

INSERT INTO table1 (First, Last)
VALUES
    ('Fred', 'Smith'),
    ('John', 'Smith'),
    ('Michael', 'Smith'),
    ('Robert', 'Smith');

Не уверен, что здесь поможет bind, скорее придётся подготовить аналогичную строку с использованием QVariantList и подать её в QSqlQuery.

Как можно динамически отображать данные в таблице? На COM-порт непрерывно приходят данные, я их принимаю сохраняю в БД, а после остановка приема/передачи данные отображаются в таблице. В таблице, которая нас интересует нужно отображать iD с которых приходят данные и количество пакетов, которое от них пришло. Пытаюсь сделать такvoid

MainWindow::newCountID(QByteArray refreshValueArr)

{
    QString id11;//Строки значений ID1, ID2 и пришедших значений
    int can1count, can2count;//Значения строк Count of Messages

    int can = refreshValueArr[0];//Значение CAN
    int sizeArr = refreshValueArr.size();

    sizeArr--;

    QByteArray idnew = refreshValueArr.remove(0, 1);//Массив пришедшего ID
    QString strId    = idnew.toHex().toUpper();     //Строка пришедшего ID

    qDebug()<<"can"<<can;
    qDebug()<<"strId****************"<<strId;

    int j = 0, i = 0;

    qDebug()<<"modelMainCAN1->rowCount()"<<modelMainCAN1->rowCount();
    if(modelMainCAN1->rowCount() > 0)//Если значения в строки уже записаны
    {
        for(i; i < modelMainCAN1->rowCount(); i++, qDebug()<<"---i---"<<i)
        {
               id11 = ui->tableViewCAN1->model()->data(//Получаем значения ячеек столбца ID
                           ui->tableViewCAN1->model()->index(i, 0)).value<QString>();
               qDebug()<<"id11------------------- "<<id11;
                if(id11 == strId)//Если строка ID такая же как уже существующая
                {
                    if(i > 0)
                    {
                        can1count = ui->tableViewCAN1->model()->data(//Получаем значения ячеек столбца Message                                                                                                                                                 
                                             ui->tableViewCAN1->model()->index(i, 2)).value<int>();//of count (то, что нужно 
                                                                                                                                          //поменять)

                            can1count++;//Меняем

                            ui->tableViewCAN1->model()->data(//Изменяем значения ячеек столбца Message of count
                            ui->tableViewCAN1->model()->index(i, 2)).setValue(can1count);//Вставляем
                            //Но не вставляется, во всяком случае на виджете не отображается, но сама форма 
                            //начинает тормозить
                        }
                        else//если такого значения нет (первый запуск) его нужно добавить
                        {
                            modelMainCAN1->insertRow(modelMainCAN1->rowCount(QModelIndex()));
                        }
                    }break;//Выходим из цикла
                }
            }


            else//если записей в таблице пока нет (но это второстепенно)
            {
                ui->tableViewCAN1->setModel(modelMainCAN1);
                //modelMainCAN1->insertRow();
            }

        
}
  • #
  • 25 сентября 2018 г. 15:24

Это запись метода которая работает параллельно с БД, данные из парсера поступают в БД и в наш метод одновременно

Может вам из того метода кидать сигнал о получении новых данных и делать апдейт таблицы по тому сигналу, чтобы была новая выборка из БД для обновления таблицы?

Сигнал кидайте в конце этого метода, который Вы привели.

Не подскажете как обновить данные в ячейке? Допустим есть строка, состоящая из 2-х столбцов если данные в первом столбце совпадают с пришедшими к значению во втором столбце просто прибавляется 1. Сигнал послал, данные принял, сравнил с данными в столбце №1, а вот значения в ячейке таблицы обновить не получается.

Постоянно обращаться к БД для обновления таблицы не получится, т.к. данные идут непрерывно.

Я так полагаю, что Вам нужно тогда перпроектировать модель данных приложения.

Базу данных используйте только как хранилище, а при динамическом изменении данных, которое у вас имеется используйте модель данных, наследованную от QAbstractItemModel. Там используйте вектор со структурами строки ваших данных. При получении данных, вставляйте запись в БД и в модель данных.

Единственный коннект модели к базе данных будет через сырую выборку SQL-запросом всех необходимых данных, и новое заполнения вектора данных в модели.

Тогда модель данных не будет постоянно обращаться к БД.

При вставке новый строк обычно используют методы beginInsertRows, endInsertRows и т.д, тогда модель будет уведомлять представление об изменениях и Table View будет автоматически перерисовываться. Также метод setData нужно использовать для обновления ячеек в таблице.

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

Тем более, что это ReadOnly модель. Она в своём базовом функционале не позволяет записывать или обновлять данные через себя.


  • #
  • 27 сентября 2018 г. 9:37
ReadOnly - теперь ясно. Спасибо, ща буду переписывать.

Из разряда "а вдруг кому-нибудь пригодится"

Для динамического обновления таблицы по мере поступления в нее данных я воспользовался контейнером QMap, т.к. у меня есть ID - они выполняют роль ключей и обновляющиеся значения (количество сообщений, которые пришли на этот ID).

Сначала пишем новый класс унаследованный от QAbstractTableMode l:

.h

#include <QMap>
#include <QDebug>
#include <QThread>
#include <QAbstractTableModel>

class MapModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    enum MapRole
    {
        KeyRole,
        ValueRole
    };
    explicit MapModel(QObject *parent = nullptr);
    int rowCount(const QModelIndex& parent = QModelIndex()) const;
    int columnCount(const QModelIndex& parent = QModelIndex()) const;
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
    inline void setMap(QMap<QString, int>* map){map6 = map;}

private:
    QMap<QString, int>* map;
};

.cpp

#include "mapmodel.h"

MapModel::MapModel(QObject *parent) : QAbstractTableModel(parent)
{
    map = nullptr;
}

int MapModel::rowCount(const QModelIndex& parent) const
{
    if(map)
        return map6->count();
    return 0;
}

int MapModel::columnCount(const QModelIndex& parent) const
{
    return 3;
}

QVariant MapModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
           return QVariant();

    if (orientation == Qt::Horizontal)
    {
        switch (section)
        {
            case 0:
                return QString("ID_Device");

            case 1:
                return QString("Number of Messages");

            default:
                return QVariant();
        }
    }
    return QVariant();
}

QVariant MapModel::data(const QModelIndex& index, int role) const
{
    if(!map)
        return QVariant();
    if(index.row() < 0 || index.row() >= map6->count() || role != Qt::DisplayRole)
    {
        return QVariant();
    }

    if(index.column() == 0)
    {
        return map->keys().at(index.row());
    }
    if(index.column() == 1)
    {
        return map->values().at(index.row());
    }
    return QVariant();
}

В методе, в котором идет обработка пришедших данных, в нужном месте прописываем какой-нибудь сигнал, который принимает необходимые нам данные, в моем случае это QByteArray

signalToMain(QByteArray arr);

Коннектим наш сигнал со слотом:

connect(parserClass, SIGNAL(signalToModelMain(QByteArray)), this, SLOT(slotFromParser(QByteArray)));

Наш слот

void MainWindow::slotFromParser(QByteArray array)
{
    static QMap<QString, int>map1;//Маппер для таблицы 

    QString id11;//Строки значений ID1

    QString strId    = array.toHex().toUpper();     //Строка пришедшего ID

    qDebug()<<"strId****************"<<strId;

    int  rows = 1;//Начальное значение QMap впервые пришедших ключа и значения

    if(map1.contains(strId))//Если контейнер содержит строку(ключ) аналогичную пришедшей
    {
        foreach(QString key, map1.keys()) //Я знаю что foreach лучше не использовать, "горбатого могила"))
        {
            int val = map1.value(key);//Получаем значение соответствующее ключу
            qDebug()<<"val" << val;

            if(strId == key)//Если пришедшая строка равна ключу на определенной позиции
            {
                ++val;//Инкрементируем счетчик
                qDebug()<<"val++1" << val;
                map1.insert(strId, val);//Вставляем в контейнер полученные значения
                break;
            }
        }
     }
     else
     {
         map1.insert(strId, rows);//Вставляем начальное значение
     }
     qDebug()<<"map1------ "<<map1;
     mapMod->setMap(&map1);//Создаем модель
     ui->tableView->setModel(mapMod);//Вставляем модель в таблицу
     ui->tableView->reset();//Перезагружаем таблицу
}

, где mapMod:

mainwindow.h

MapModel   *mapMod;

mainwindow.cpp

mapMod = new MapModel();
#include "mapmodel.h"

MapModel::MapModel(QObject *parent) : QAbstractTableModel(parent)
{
    map6 = nullptr;
}

int MapModel::rowCount(const QModelIndex& parent) const
{
    if(map6)
        return map6->count();
    return 0;
}

int MapModel::columnCount(const QModelIndex& parent) const
{
    return 3;
}

QVariant MapModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
           return QVariant();

    if (orientation == Qt::Horizontal)
    {
        switch (section)
        {
            case 0:
                return QString("ID_Device");

            case 1:
                return QString("Number of Messages");

            default:
                return QVariant();
        }
    }
    return QVariant();
}

QVariant MapModel::data(const QModelIndex& index, int role) const
{
    if(!map6)
        return QVariant();
    if(index.row() < 0 || index.row() >= map6->count() || role != Qt::DisplayRole)
    {
        return QVariant();
    }

    if(index.column() == 0)
    {
        return map6->keys().at(index.row());
    }
    if(index.column() == 1)
    {
        return map6->values().at(index.row());
    }
    return QVariant(); 

} не получается подредактировать

private:
    QMap<QString, int>* map6;



В Qt 5.11. при попытке вставить в БД запись выдает ошибку

QSqlQuery::prepare: database not open

QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
как с этим бороться?




Попробуйте передать инстанс базы данных в конструктор QSqlQuery

QSqlQuery q(db);

Не получается

bool DataBase::insertDataIntoDB(QVariantList data)
{
    QSqlQuery query(db);
    QString   str;
    qDebug()<<"InsertInsertInsertInsertInsert"<<QThread::currentThreadId();;

    int count = data.count();
    int N = count/5;
    qDebug()<<"N"<<N;

    str = "INSERT INTO DataBase    ("
                       "DTTable,    "
                       "CANTable,   "
                       "ID_Device,  "
                       "DlcCan,     "
                       "Message    )"
          "VALUES (?, ?, ?, ?, ?)";
    QSqlDatabase::database().transaction();
    for(int i = 0, j = 0; i < N; i++)
    {
        query.prepare(str);
        query.addBindValue(data[j]);
        query.addBindValue(data[++j]);
        query.addBindValue(data[++j]);
        query.addBindValue(data[++j]);
        query.addBindValue(data[++j]);
        query.exec();
        ++j;
    }
    query.exec();
    //qDebug()<<data;

    QSqlDatabase::database().commit();

    if(!query.exec())
    {
        qDebug()<<"Error insert into DataBase";
        qDebug()<<query.lastError().text();
        return false;
    }
    else
    {
        qDebug()<<"Insert compleated";
        return true;
    }
}





Как-то даже странно, а вы что ли в отдельный поток убрали базу данных? То есть изначально инстанс создаётся в одном потоке, а все QSqlQuery в другом потоке? Они должны находиться в одном потоке так-то.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
A
22 января 2019 г. 21:22
Allyonz

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

  • Результат:40баллов,
  • Очки рейтинга-8
A
22 января 2019 г. 14:15
Alex

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

  • Результат:89баллов,
  • Очки рейтинга6
IO
20 января 2019 г. 18:39
Ivan Otreshko

C++ - Тест 003. Условия и циклы

  • Результат:0баллов,
  • Очки рейтинга-10
Последние комментарии
22 января 2019 г. 13:17
Евгений Легоцкой

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

Не проще тогда использовать сразу кастомный делегат с чекбоксом? Я попробовал, но там засада в том, что чекбокс показывается только при щелчке на ячейку, а дефолтно показывается значение. Как ...
22 января 2019 г. 12:15
Евгений Легоцкой

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

Получилось приемлемо. Спасибо!Нюанс только в том, что поле рядом с чекбоксом не пропадает, оно просто пустое, что видно при выделении ячейки. Но этого достаточно.
22 января 2019 г. 11:50
Евгений Легоцкой

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

Зарание спасибо.А еще на эту тему можно будет сделать статью. Это контент будет уникальным.
23 января 2019 г. 7:37
Евгений Легоцкой

Hello. Maybe the English will be better for you? I think russian is not native language for you, or did I mistake? Did I undesrtood rightly, that you mean this documentation ( ...
I
22 января 2019 г. 13:45
IscanderChe

Всем добрый день. Суть задачи: надо, чтобы в одной из колонок QTableView вместо хранимого в QSqlTableModel значения выводился чекбокс и при смене состояния чекбокса значения в базе тоже ...
M
22 января 2019 г. 13:15
Max-P85

Евгений, огромное спасибо, все работает!
Присоединяйтесь к нам в социальных сетях

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