Ruslan Polupan24 апреля 2019 г. 6:07
Помогите разобраться с 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 хостинг.Вам это нравится? Поделитесь в социальных сетях!
Комментарии
Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Пожалуйста, авторизуйтесь или зарегистрируйтесь
l
- laei
- 23 апреля 2024 г. 9:19
C++ - Тест 004. Указатели, Массивы и Циклы
- Результат:10баллов,
- Очки рейтинга-10
Последние комментарии
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Анатолий Кононенко5 февраля 2024 г. 1:50
EVA25 декабря 2023 г. 10:30
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
DA
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
Dr Gangil Academics20 апреля 2024 г. 7:45
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев14 апреля 2024 г. 2:35
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
Добрый день
А вот этот код
Не должен быть написан так?
Согласен. но ситуация не поменялась. Такое чуство что данные не записываются в модель.
Думаю, что в методе setData нужно в роли Qt::EditRole делать установку значения. Скорее всего у вас просто не заходит в ту ветку кода выполнение программы. Обычно для установки значения используется именно роль Qt::EditRole
Изменил функцию
теперь работает.
Продолжаем вопросы... (Сори если что :-)
Как теперь отловить сигнал checked от делегата?
Пока сделал так:
Где:
но это отрабатывает изменение модели
А вот сам клик на checkbox бы отловить...
Ну по идее есть такой сигнал commitData у делегатов. В данном сигнале высылается указатель на виджет перед записью данных в модель. Можете попробовать на его основе что-то сообразить.
Еще обнаружил такую ситуацию. Оказывается данные в модель записываются, лиш после того как фокус получает любой item TableView.
Т.е. Состояние CheckBox записывается в модель не при изменении его статуса а лишь тогда когда с него теряется фокус.
Ну в общем-то да, есть такая ситуация. Думаю, что это правильное поведение. Дело в том, что если логика под капотом очень сложная и влияет на большое количество компонентов, то апдейт при редактировании может очень сильно уменьшить скорость работы софта, поскольку такие апдейты будут выполняться тогда, когда по факту в 99% случае они вовсе не нужны.
Реализовать такую ситуацию:
Я выбрал несколько строк и не прешел на другую ячейку а нажал кнопку "Выполнить" например.
И тогда получается что последняя мною выбранная запись не попадет для дальнейшей обработки.
Или есть таки способ принудительно опросить делегаты и записать их состояние в модель?