А тепер невелика стаття про кастомізації поведінки осередків за допомогою делегатів в QTableView.
Ця стаття є модифікацією поведінки таблиці в одній старій статті, а саме
Qt/C++ - Урок 039. Як зафарбувати рядок в QSqlTableModel за значенням в стовпці
. По суті та стара стаття не має впливу на вміст даної статті, але таблиця для прикладу буде взята з того уроку.
Як завдання вибрано зміна кольору рядка при наведенні курсору миші.
Виглядати це буде наступним чином
Для реалізації подібного функціоналу напишемо клас CustomDelegate, який буде встановлюватися в колонки таблиці, щоб управляти перефарбою фону осередків.
CustomDelegate.h
Наслідуючи від класу QStyledItemDelegate і перевизначати метод paint .
- #ifndef CUSTOMDELEGATE_H
- #define CUSTOMDELEGATE_H
- #include <QStyledItemDelegate>
- class CustomDelegate : public QStyledItemDelegate
- {
- using BaseClass = QStyledItemDelegate;
- public:
- CustomDelegate(QObject* parent = nullptr);
- virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
- };
- #endif // CUSTOMDELEGATE_H
CustomDelegate.cpp
У методі paint ми перевіряємо, чи знаходиться курсор на одній в рядку клітинки, яка піддалася перемальовуванні в процес руху курсору в області QTableView керування, і якщо це так, то заповнюємо фон комірки необхідним кольором.
- #include "customdelegate.h"
- #include <QPainter>
- #include <QAbstractItemView>
- CustomDelegate::CustomDelegate(QObject* parent) : BaseClass(parent)
- {
- }
- void CustomDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
- {
- if (QAbstractItemView* tableView = qobject_cast<QAbstractItemView*>(this->parent()))
- {
- QModelIndex hover = tableView->indexAt(tableView->viewport()->mapFromGlobal(QCursor::pos()));
- if (hover.row() == index.row())
- {
- painter->fillRect(option.rect, Qt::red);
- }
- }
- BaseClass::paint(painter, option, index);
- }
Установка делегата в QTableView
Делегат повинен встановлюватися в кожну колонку в таблиці. А також необхідно включити відстеження пересування курсору миші всередині QTableView.
- ui->tableView->setItemDelegateForColumn(0, new CustomDelegate(ui->tableView));
- ui->tableView->setItemDelegateForColumn(1, new CustomDelegate(ui->tableView));
- ui->tableView->setItemDelegateForColumn(2, new CustomDelegate(ui->tableView));
- ui->tableView->setItemDelegateForColumn(3, new CustomDelegate(ui->tableView));
- ui->tableView->setItemDelegateForColumn(4, new CustomDelegate(ui->tableView));
- ui->tableView->setMouseTracking(true);
Висновок
Дуже важливо розуміти, яка частина коду і за що відповідає з точки зору архітектури програми.
Пересування курсора миші є виключно користувальницької активністю, яка не має ніякого відношення до даних.
Тому намагайтеся уникати додавання подібного функціоналу в модель даних, оскільки це спочатку буде неправильним підходом.
Краще написати трохи більше програмного коду і використовувати делегат, ніж змішувати дані і їх уявлення.
Тобто в такому разі зміна поведінки програми не повинно опускатися нижче кончини або окремого делегат уявлення.
День добрый.
Зачем нужна вот эта строка:
Всё, разобрался. :)
Добрый день. Удобства ради. В больших проектах удобнее вызывать BaseClass, чем постоянно смотреть, от чего конкретно наследован текущий класс. Экономит время.
Код делегата полностью скопировал в свой тестовый проект, но окрашивается не вся строка целиком, а только ячейка, на которую указывает курсор.
Во все колонки установили? Нужно на все колонки устанавливать.
Да, во все колонки.
Полностью скопировал пример - всё правильно работает. Значит, где-то у меня ошибки в тестовом проекте. Буду разбираться. Извините за беспокойство. :)
Разобрался. У вас изначально в проекте были вот эти настройки:
У меня же их не было, поэтому и выделялись отдельные ячейки.
Понятно. Я не обратил внимания на то, что там было в старом коде по настройкам строк :)
Сижу, размышляю: можно ли переписать делегата так, чтобы независимо от настроек строк выделялись строки?
По-моему, смысла в этом нет особого. Если делегат будет игнорировать настройки таблицы, то это приведёт ещё к большему непониманию, что вообще происходит, для программиста, который после вас будет смотреть на ваш проект.