Помогите разобраться с 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);
- }
- }
2
253
Do you like it? Share on social networks!
- Last comments
- AKApril 1, 2025, 11:41 a.m.Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
- VPMarch 9, 2025, 4:14 p.m.Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
- ИМNov. 22, 2024, 9:51 p.m.Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
- Now discuss on the forum
- МАApril 1, 2025, 4:21 p.m.0ff763fe-4e50-455d-a3a6-5699c243b1a5_17_44_22_1.xml
- fFeb. 15, 2025, 1:46 p.m.Подскажите, пожалуйста! Как данный класс можно дополнить, чтобы созданные объекты можно было перемещать мышкой по сцене?
- Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
- Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
Добрый день
А вот этот код
Не должен быть написан так?
Согласен. но ситуация не поменялась. Такое чуство что данные не записываются в модель.
Думаю, что в методе setData нужно в роли Qt::EditRole делать установку значения. Скорее всего у вас просто не заходит в ту ветку кода выполнение программы. Обычно для установки значения используется именно роль Qt::EditRole
Изменил функцию
теперь работает.
Продолжаем вопросы... (Сори если что :-)
Как теперь отловить сигнал checked от делегата?
Пока сделал так:
Где:
но это отрабатывает изменение модели
А вот сам клик на checkbox бы отловить...
Ну по идее есть такой сигнал commitData у делегатов. В данном сигнале высылается указатель на виджет перед записью данных в модель. Можете попробовать на его основе что-то сообразить.
Еще обнаружил такую ситуацию. Оказывается данные в модель записываются, лиш после того как фокус получает любой item TableView.
Т.е. Состояние CheckBox записывается в модель не при изменении его статуса а лишь тогда когда с него теряется фокус.
Ну в общем-то да, есть такая ситуация. Думаю, что это правильное поведение. Дело в том, что если логика под капотом очень сложная и влияет на большое количество компонентов, то апдейт при редактировании может очень сильно уменьшить скорость работы софта, поскольку такие апдейты будут выполняться тогда, когда по факту в 99% случае они вовсе не нужны.
Реализовать такую ситуацию:
Я выбрал несколько строк и не прешел на другую ячейку а нажал кнопку "Выполнить" например.
И тогда получается что последняя мною выбранная запись не попадет для дальнейшей обработки.
Или есть таки способ принудительно опросить делегаты и записать их состояние в модель?