Evgenii Legotckoi
Evgenii Legotckoi03 червня 2020 р. 17:30

Qt/C ++ - Урок 091. Як написати кастомний делегат керуючий підсвічуванням рядки в таблиці

А тепер невелика стаття про кастомізації поведінки осередків за допомогою делегатів в 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);

Висновок

Дуже важливо розуміти, яка частина коду і за що відповідає з точки зору архітектури програми.
Пересування курсора миші є виключно користувальницької активністю, яка не має ніякого відношення до даних.
Тому намагайтеся уникати додавання подібного функціоналу в модель даних, оскільки це спочатку буде неправильним підходом.
Краще написати трохи більше програмного коду і використовувати делегат, ніж змішувати дані і їх уявлення.
Тобто в такому разі зміна поведінки програми не повинно опускатися нижче кончини або окремого делегат уявлення.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

IscanderChe
  • 04 червня 2020 р. 06:30
  • (відредаговано)

День добрый.
Зачем нужна вот эта строка:

using BaseClass = QStyledItemDelegate;

Всё, разобрался. :)

Evgenii Legotckoi
  • 04 червня 2020 р. 07:12
  • (відредаговано)

Добрый день. Удобства ради. В больших проектах удобнее вызывать BaseClass, чем постоянно смотреть, от чего конкретно наследован текущий класс. Экономит время.

IscanderChe
  • 04 червня 2020 р. 07:59

Код делегата полностью скопировал в свой тестовый проект, но окрашивается не вся строка целиком, а только ячейка, на которую указывает курсор.

Evgenii Legotckoi
  • 04 червня 2020 р. 08:08

Во все колонки установили? Нужно на все колонки устанавливать.

IscanderChe
  • 04 червня 2020 р. 08:10

Да, во все колонки.

IscanderChe
  • 04 червня 2020 р. 12:10

Полностью скопировал пример - всё правильно работает. Значит, где-то у меня ошибки в тестовом проекте. Буду разбираться. Извините за беспокойство. :)

IscanderChe
  • 05 червня 2020 р. 02:27

Разобрался. У вас изначально в проекте были вот эти настройки:

ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);

У меня же их не было, поэтому и выделялись отдельные ячейки.

Evgenii Legotckoi
  • 05 червня 2020 р. 02:31

Понятно. Я не обратил внимания на то, что там было в старом коде по настройкам строк :)

IscanderChe
  • 05 червня 2020 р. 02:34

Сижу, размышляю: можно ли переписать делегата так, чтобы независимо от настроек строк выделялись строки?

Evgenii Legotckoi
  • 05 червня 2020 р. 02:39

По-моему, смысла в этом нет особого. Если делегат будет игнорировать настройки таблицы, то это приведёт ещё к большему непониманию, что вообще происходит, для программиста, который после вас будет смотреть на ваш проект.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
e
  • ehot
  • 01 квітня 2024 р. 02:29

C++ - Тест 003. Условия и циклы

  • Результат:78бали,
  • Рейтинг балів2
B
  • Bogdannn
  • 28 березня 2024 р. 07:21

C++ - Тест 002. Константы

  • Результат:16бали,
  • Рейтинг балів-10
B
  • Bogdannn
  • 28 березня 2024 р. 07:15

C++ - Тест 001. Первая программа и типы данных

  • Результат:46бали,
  • Рейтинг балів-6
Останні коментарі
k
kmssr09 лютого 2024 р. 07:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 14:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 23:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 грудня 2023 р. 21:38
Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik19 грудня 2023 р. 10:01
Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Тепер обговоріть на форумі
a
a_vlasov14 квітня 2024 р. 18:41
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел Дорофеев14 квітня 2024 р. 14:35
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrex04 квітня 2024 р. 16:47
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
P
Pisych27 лютого 2023 р. 17:04
Как получить в массив значения из связанной модели? Спасибо, разобрался:))
AC
Alexandru Codreanu20 січня 2024 р. 00:57
QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…

Слідкуйте за нами в соціальних мережах