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