А тепер невелика стаття про кастомізації поведінки осередків за допомогою делегатів в 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, чем постоянно смотреть, от чего конкретно наследован текущий класс. Экономит время.
Код делегата полностью скопировал в свой тестовый проект, но окрашивается не вся строка целиком, а только ячейка, на которую указывает курсор.
Во все колонки установили? Нужно на все колонки устанавливать.
Да, во все колонки.
Полностью скопировал пример - всё правильно работает. Значит, где-то у меня ошибки в тестовом проекте. Буду разбираться. Извините за беспокойство. :)
Разобрался. У вас изначально в проекте были вот эти настройки:
У меня же их не было, поэтому и выделялись отдельные ячейки.
Понятно. Я не обратил внимания на то, что там было в старом коде по настройкам строк :)
Сижу, размышляю: можно ли переписать делегата так, чтобы независимо от настроек строк выделялись строки?
По-моему, смысла в этом нет особого. Если делегат будет игнорировать настройки таблицы, то это приведёт ещё к большему непониманию, что вообще происходит, для программиста, который после вас будет смотреть на ваш проект.