Evgenij LegotskojJune 3, 2020, 5:30 p.m.

Qt/C++ - Tutorial 091. How to write a custom delegate controlling the highlighting of a row in a table

Content

And now a short article on customizing cell behavior using delegates in a QTableView.
This article is a modification of the table behavior in one old article, namely Qt/C ++ - Tutorial 039. How to fill a row in QSqlTableModel by the value in the column . In fact, that old article has no effect on the contents of this article, but the table for an example will be taken from that lesson.

As the task, the color of the line was selected when the mouse cursor was over.

It will look as follows

To implement this functionality, we will write the CustomDelegate class, which will be installed in the table columns to control the repainting of the background of the cells.перекраской фона ячеек.

CustomDelegate.h

We inherit from the QStyledItemDelegate class and override the paint method.

#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

In the paint method, we check if the cursor is on one in the row of the cell that underwent redrawing during the cursor movement in the QTableView area of the widget, and if so, then fill the cell background with the desired color.

#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);
}

Setting a delegate to a QTableView

A delegate must be installed in each column in the table. And you also need to enable mouse cursor tracking inside 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);

Conclusion

It is very important to understand what part of the code and for what is responsible from the point of view of the program architecture.
The movement of the mouse cursor is an exclusively user activity that has nothing to do with data.
Therefore, try to avoid adding such functionality to the data model, as this would initially be the wrong approach.
It is better to write a little more code and use a delegate than to mix data and its presentation.
That is, in such a case, a change in the behavior of the program should not fall below the presentation or the individual delegate of the presentation.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
- company blog
Support the author Donate

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

using BaseClass = QStyledItemDelegate;

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

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

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

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

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

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

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

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

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

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

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

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

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
k
  • knobu
  • Sept. 23, 2020, 2:34 a.m.

C++ - Test 006. Enumerations

  • Result:60points,
  • Rating points-1
k
  • knobu
  • Sept. 23, 2020, 2:21 a.m.

C++ - Test 005. Structures and Classes

  • Result:91points,
  • Rating points8
k
  • knobu
  • Sept. 23, 2020, 2:16 a.m.

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:80points,
  • Rating points4
Last comments

Qt/C++ - Lesson 006. QSqlQueryModel – Tables in Qt with SQL-query

QSqlTableModel выполняет ряд стандартных операций для одной таблицы из базы данных. Поэтому там и реализован функционал по удалению и редактированию. QSqlQueryModel позволяет выполнить запр…
VB

Qt/C++ - Lesson 006. QSqlQueryModel – Tables in Qt with SQL-query

Добрый день. Хотел спросить вот что. Создал проект на основе QAbstractTableModel. В MainWindow cоответственно создал модель и связал с представлением. Поиск веду по списку элементов модели,…

QCheckBox в качестве делегата QTableView

До тех пор, пока у вас проект содержит только одну таблицу, или несколько то может быть. Когда их будет 1000 и чекбоксы в разных колонках, то без делегатов и переопределения возвращаемых ре…
D
  • Damir
  • Sept. 20, 2020, 3:34 p.m.

QCheckBox в качестве делегата QTableView

bool Node::setData(const QModelIndex& index, const QVariant& value, int role){ switch (index.column()) { case 0: switch (role) { case Qt::CheckStateRole:// <- т…
VB

Qt/C++ - Lesson 004. QSqlTableModel – How to present the table from database?

Почему-то такой метод для обновления не работает, который можно было бы применить в данном примере. То есть в представлении данные удаляются и обновляются, а в базе данных изменений не происходи…
Now discuss on the forum

Как в Qt в qmenu добавить scrollarea

Вот это наследованный класс меню. Но посути это обычное меню. #pragma once#include <QtWidgets>class TransMenu : public QMenu { Q_OBJECTpublic: TransMenu(QWidget* parent = …

Как в qml работать с динамически созданными потомками?

В QML есть сборщик мусора, он может удалять объекты не сразу а по ппрошествии времени. Попробуйте при удалении вызывать сборщик мусора принудительно через gc()
VB

Как запустить программу с базой данных PostgreSQL на другом компьютере

Не требует никакую библиотеку, запускается на других компьютерах, где не установлена PostgreSQL, но создать элемент невозможно, тем более отредактировать или удалить.
p
  • prod1s
  • Sept. 24, 2020, 7:12 a.m.

через QT не могу открыть файл SQLite

Вирішення знайшов. Вказав замість назви БД об'єкт класу QSqlDataBase для QSqlQuery. QSqlQuery m_query = QSqlQuery(qSqlDataBase); Після двох днів пошуку рішення, все-таки знайшов…
U

как скрыть елемент с копии виджета

Дело в том, что ui класса находится в private-секции... И из-вне доступ получить, не нарушая канонов - не получится) Можно конечно сделать что-то в духе #define private public, но это для истинн…
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB