Создаем делегат для QTableView - Работа с моделями в Qt5 для отображения данных в виджетах. - АлтунинВВ.Блог - всё об IT-технологиях!
Пятница, 25 декабря 2020 19:00

Создаем делегат для QTableView - Работа с моделями в Qt5 для отображения данных в виджетах.

Россия
Оцените материал
(0 голосов)

В Qt5 ячейки таблицы могут содержать не только текст, но и другие виджеты.

Сегодня мы создадим простой делегат для QTableView, чтобы отобразить в столбце иконку. Для того чтобы сэкономить время, мы будем проект из прошлой статьи.

Так же нам понадобиться файлы из этой статьи - скопируйте папку img и файл resource.qrc и добавьте в проект.

Откроем главную форму и сделаем её немного шире - нам понадобиться дополнительное место.

Добавим новый класс Делегата - TableItemDelegate:

Заголовок:

#ifndef TableITEMDELEGATE_H
#define TableITEMDELEGATE_H

#include <QItemDelegate>
#include <QPolygonF>
#include <QPointF>

class TableItemDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    TableItemDelegate();

    QSize sizeHint(const QStyleOptionViewItem &option,
                       const QModelIndex &index) const override;

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
                  const QModelIndex &index) const override;
};

#endif // TableITEMDELEGATE_H

Реализация

#include "tableitemdelegate.h"
#include "math.h"

#include <QPainter>
#include <QDebug>


TableItemDelegate::TableItemDelegate()
{

}

QSize TableItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    return QItemDelegate::sizeHint(option, index);
}

void TableItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
  QStyleOptionViewItem myOption = option;

    if (index.column()==2)
    {
        QString data = index.model()->data(index, Qt::DisplayRole).toString();


        myOption.displayAlignment = Qt::AlignCenter | Qt::AlignVCenter;

        QString icon = ":/img/" + index.model()->data(index, Qt::DisplayRole).toString();

        qDebug() << icon;

        QPixmap pixmap2(icon);

        painter->drawPixmap(myOption.rect.x()+30,myOption.rect.y(),32,32, pixmap2);
    }
    else
    {
        drawDisplay(painter, option, option.rect, index.model()->data(index, Qt::DisplayRole).toString());
        
    }
	drawFocus(painter, myOption, myOption.rect);


}

Запустим:

2020-12-25_10-37-15.png

В третьем столбце у нас появились иконки.

Код делегата не сильно поменялся, по сравнению с тем, что мы использовали для QComboBox. Единственное отличие – мы проверяем номер столбца. Если это третий столбец – то рисуем иконку, если любой другой - вызываем метод рисования по умолчанию – drawDisplay.

И в любом случае отрисовываем рамку фокуса drawFocus

Предположим, что нам необходимо отображать так же и имя файла, в добавок к самой иконке.

Внесем изменения в модель - изменим количество столбцов:

int QTableViewModel::columnCount(const QModelIndex &) const
{
    return 4;
}

Изменим метод data() 

QVariant QTableViewModel::data( const QModelIndex &index, int role ) const
{

    QVariant value;

        switch ( role )
        {
            case Qt::DisplayRole: //string
            {
                switch (index.column()) {
                    case 0: {
                        value = this->values->at(index.row()).getId();
                        break;
                    }
                    case 1: {
                        value = this->values->at(index.row()).getName();
                        break;
                    }
                    case 2: {
                        value = this->values->at(index.row()).getIcon();
                        break;
                    }
                    case 3: {
                        value = this->values->at(index.row()).getIcon();
                        break;
                    }
                }
            }
            break;

            case Qt::UserRole: //data
            {
                value = this->values->at(index.row()).getId();
            }
            break;

            default:
                break;
        }

    return value;
}

Здесь мы просто увеличили количество столбцов, возвращаемых методом columnCount() и в метод data() добавили возврат данных для столбца 4.

Запустим:

2020-12-25_10-37-34.png

Чего-то не хватает - мы забыли про заголовок столбца:

QVariant QTableViewModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
        switch (section) {
        case 0:
            return QString("ID");
        case 1:
            return QString("Name");
        case 2:
            return QString("Icon");
        case 2:
            return QString("Icon file");
        }
    }
    return QVariant();
}

Запустим:

2020-12-25_10-39-14.png

Вот мы и добавили новый столбец, с добавлением дополнительных столбцов не должно возникнуть проблем - всё что нужно увеличить количество столбцов и добавить возврат значения в метод data().

Заключение

Сегодня мы написали простой Делегат модель для QTableView, при этом нам даже не пришлось менять нашу модель.

Так же мы добавили новый столбец в таблицу, для отображения имени файла иконки.

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

Исходный код вы можете найти на Github.

Прочитано 417 раз Последнее изменение Среда, 13 января 2021 12:13