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