Помогите разобраться с CheckBox delegate в QAbstractTableModel
Delegate, qcheckbox, QAbstractTableModel
Доброго времени суток.
Где то я упустил что-то при изучении делегатов и их использовании.
Отображение работает. Но после того как выбираешь другую строку таблицы, предидущее выделение сбрсывается.
Не получается выбрать несколько объектов.
Файлы реализации делегата CheckBoxDelegate использовал такие же как в этой статье https://evileg.com/ru/post/478/
Реализация модели
modelterminals.h
#ifndef MODELTERMINALS_H #define MODELTERMINALS_H #include "terminalclass.h" #include <QObject> #include <QAbstractTableModel> class ModelTerminals : public QAbstractTableModel { Q_OBJECT QList<TerminalClass> m_listTerm; public: ModelTerminals(QList<TerminalClass> lsTerm); // QAbstractItemModel interface public: int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; }; #endif // MODELTERMINALS_H
modelterminals.cpp
#include "modelterminals.h" ModelTerminals::ModelTerminals(QList<TerminalClass> lsTerm ) : m_listTerm(lsTerm) { } int ModelTerminals::rowCount(const QModelIndex &parent) const { return m_listTerm.size(); Q_UNUSED(parent) } int ModelTerminals::columnCount(const QModelIndex &parent) const { return m_listTerm.at(0).colParam(); Q_UNUSED(parent) } QVariant ModelTerminals::data(const QModelIndex &index, int role) const { if(!index.isValid()) { return QVariant();} TerminalClass t = m_listTerm[index.row()]; switch (role) { case Qt::DisplayRole: switch (index.column()) { case 0: return t.isCheced(); case 1: return t.terminalID(); case 2: return t.terminalName(); case 3: return t.regionID(); case 4: return t.serverName(); } break; case Qt::CheckStateRole: if(index.column() == 0) { return (!t.isCheced()) ? Qt::Checked : Qt::Unchecked; } break; default: break; } return QVariant(); } bool ModelTerminals::setData(const QModelIndex &index, const QVariant &value, int role) { if(!index.isValid()) {return false;} TerminalClass t = m_listTerm[index.row()]; if(role == Qt::CheckStateRole){ if(value.toInt() == Qt::Checked){ t.setIsCheced(true); } else { t.setIsCheced(false); } emit dataChanged(index,index); return true; } return false; } Qt::ItemFlags ModelTerminals::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractTableModel::flags(index); if(index.isValid() && index.column() == 0){ flags |= Qt::ItemIsEditable; } return flags; } QVariant ModelTerminals::headerData(int section, Qt::Orientation orientation, int role) const { if( role != Qt::DisplayRole) { return QVariant();} if( orientation == Qt::Vertical ) { return section; } switch (section) { case 0: return ""; case 1: return "АЗС"; case 2: return "Адрес"; case 3: return "Регион"; case 4: return "Сервер"; default: break; } return QVariant(); }
Получаю данные для модели и создаю модель
#include "fuelnamedialog.h" #include "ui_fuelnamedialog.h" FuelNameDialog::FuelNameDialog(QWidget *parent) : QDialog(parent), ui(new Ui::FuelNameDialog) { ui->setupUi(this); createListTerminals(); createModelterminals(); } FuelNameDialog::~FuelNameDialog() { delete ui; } void FuelNameDialog::createModelterminals() { qInfo(logInfo()) << "Заружено терминалов:" << listTerminals.size(); CheckBoxDelegate *delegate = new CheckBoxDelegate(); modelTerminals = new ModelTerminals(listTerminals); ui->tableViewTerminals->setModel(modelTerminals); ui->tableViewTerminals->setItemDelegateForColumn(0,delegate); ui->tableViewTerminals->verticalHeader()->hide(); ui->tableViewTerminals->resizeColumnsToContents(); } void FuelNameDialog::createListTerminals() { QSqlQuery q; TerminalClass t; if(!q.exec("SELECT t.TERMINAL_ID, TRIM(t.name) AS NAME, t.OWNER_ID AS REGION, c.SERVER_NAME FROM TERMINALS t " "LEFT JOIN CONNECTIONS c ON c.TERMINAL_ID = t.TERMINAL_ID " "WHERE t.TERMINALTYPE = 3 AND c.CONNECT_ID = 2 " "ORDER BY t.TERMINAL_ID")) { qInfo(logInfo()) << Q_FUNC_INFO << "Не возможно получить список терминалов" << q.lastError().text(); return; } while(q.next()){ t.setIsCheced(false); t.setTerminalID(q.value(0).toInt()); t.setTerminalName(q.value(1).toString()); t.setRegionID(q.value(2).toInt()); t.setServerName(q.value(3).toString()); listTerminals.append(t); } }
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.Вам це подобається? Поділіться в соціальних мережах!
- Akiv Doros
- 11 листопада 2024 р. 14:58
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:50бали,
- Рейтинг балів-4
- molni99
- 26 жовтня 2024 р. 01:37
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:80бали,
- Рейтинг балів4
- molni99
- 26 жовтня 2024 р. 01:29
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:20бали,
- Рейтинг балів-10
Добрый день
А вот этот код
Не должен быть написан так?
Согласен. но ситуация не поменялась. Такое чуство что данные не записываются в модель.
Думаю, что в методе setData нужно в роли Qt::EditRole делать установку значения. Скорее всего у вас просто не заходит в ту ветку кода выполнение программы. Обычно для установки значения используется именно роль Qt::EditRole
Изменил функцию
теперь работает.
Продолжаем вопросы... (Сори если что :-)
Как теперь отловить сигнал checked от делегата?
Пока сделал так:
Где:
но это отрабатывает изменение модели
А вот сам клик на checkbox бы отловить...
Ну по идее есть такой сигнал commitData у делегатов. В данном сигнале высылается указатель на виджет перед записью данных в модель. Можете попробовать на его основе что-то сообразить.
Еще обнаружил такую ситуацию. Оказывается данные в модель записываются, лиш после того как фокус получает любой item TableView.
Т.е. Состояние CheckBox записывается в модель не при изменении его статуса а лишь тогда когда с него теряется фокус.
Ну в общем-то да, есть такая ситуация. Думаю, что это правильное поведение. Дело в том, что если логика под капотом очень сложная и влияет на большое количество компонентов, то апдейт при редактировании может очень сильно уменьшить скорость работы софта, поскольку такие апдейты будут выполняться тогда, когда по факту в 99% случае они вовсе не нужны.
Реализовать такую ситуацию:
Я выбрал несколько строк и не прешел на другую ячейку а нажал кнопку "Выполнить" например.
И тогда получается что последняя мною выбранная запись не попадет для дальнейшей обработки.
Или есть таки способ принудительно опросить делегаты и записать их состояние в модель?