Раскраска ячеек в QTableView

Dec 11, 2012 17:13

Окрасить ячейку представления QTableView можно 2-мя способами:
1) Создать новый класс от QTableModel (QSQLTableModel) и переопределить метод Qvariant data(...) - class MyTM : public QTableModel { ... }
2) Создать делегат и настроить QTableView на отображение этого делегата.

Я пошёл по второму пути:

мой делегат раскрашивает ячейки в зависимости от того насколько время в ячейке отличается от текущего

хедер прост до безобразия
//-------------------------------------------------------------------------------------------------------
class STimeDelegate : public QItemDelegate
{
Q_OBJECT
public:
  STimeDelegate(QObject *parent = 0);
 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
//-------------------------------------------------------------------------------------------------------

cpp
//-------------------------------------------------------------------------------------------------------
void
STimeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//  так получилось, что в сырых данных в QSqlTableModel находятся избыточные данные дата и время, а отображать нужно только время
//    поэтому делаем некоторые манипуляции для отсечения ненужного
//      в моём случае в ячейки запросом возвращается тип не DateTime, а string - поэтому я делаю toString()? а потом fromString(...)
    QString res = index.model()->data(index, Qt::DisplayRole).toString();
    QTime time = QDateTime::fromString(res, "dd.MM.yyyy HH:mm" ).time();

//  в куы содержатся данные, которые увидит пользователь
    res = time().toString("HH:mm");

//  выравниваем по центру ячейки
    QStyleOptionViewItem myOption = option;
    myOption.displayAlignment = Qt::AlignHCenter | Qt::AlignVCenter;

//  а вот отсюда начинается магия:  сравниваем время в ячейке с текущим временем +-3 минуты
//    Важно!!! старайтесь сделать как можно меньше вычислений, ведь эта функция будет вызываться для каждой ячейки, где необходима
//      такая обработка при её перерисовке
//  для программиста проще написать 3*60 вместо 180, но это лишние вычисления, поэтому я и написал количество секунд вместо вычислений
    if (time < QTime::currentTime().addSecs(180) )
    {
// наш клиент т.к. красим в зелёный те записи, что   +- 3 минуты, оранжевым что отстают на 15 минут и красным на 30 минут

if (time > QTime::currentTime().addSecs(-180))
        {   
        //  каким цветом,   QBrush может принимать и градиенты
            QBrush br(QColor(204, 255, 204));
            painter->setBrush(br);

//   какую область
            QRect rect = option.rect;
            painter->drawRect(rect);
        }
        else if (time > QTime::currentTime().addSecs(-900))
        {
        //  в первом вложеном bat я описал по шагам, тут же сокращу
            painter->setBrush( QBrush (QColor(255, 204, 51)) );
            painter->drawRect(option.rect);
        }
        else if (time > QTime::currentTime().addSecs(-1800))
        {
            painter->setBrush( QBrush (QColor(255, 153, 153)) );
            painter->drawRect(option.rect);
        }

}

//  рисуем всё что наделали
    drawDisplay(painter, myOption, myOption.rect, res);
    drawFocus(painter, myOption, myOption.rect);
}

Это ещё не всё необходимо связать представление с делегатом:
Cpp  формы, где лежит view:
// т.к. мой делегат действует только на 1 колонку, гда показывается время, то
  view->setItemDelegateForColumn( model->fieldIndex("DateTime"), new SStatDelegate() );

теперь всё

Дополнение:

Так же может возникнуть необходимость динамически изменять параметры выделения. Например я своим пользоователям дал возможность выбирать как далеко во времени от сейчас должны отстоят раскрашиваемые в тот или другой цвет

при помощи немного модифицированного меню из прошлого поста пользователь может вместо 3, 15 и 30 жёстко зашитых минут, может выбрать свои параметры. Я покажу как для это модифицировать описанный выше делегат:

создаём метку определитель (я не знаю как оно правильно называется) что-то вроде константы. Дабы в большом объёме кода не напутать со строками, то "C" вместо английской русская, то какой-то символ пропустил...
#define Range1 = "Range1"
#define Range2 = "Range2"
#define Range2 = "Range3"

в слоте нажатия пункта меню пишем:
qApp->setProperty(Range1, act->data());    // да, тот же механизм copyPaste, что опиывал в первом посте. только data у нас QVariant и не нужно никуда конвертировать. или Range2 ... в зависимости от логики программы

теперь возвращаемся в cpp делегата:
и заменяем жёсткие цифры, на "мягкие" property. Тут уже превращаем вариант в инт ибо секунды
if (time < QTime::currentTime().addSecs( qApp->property(Range1).toInt()) )
...

Вот такой Шикарный механизм буффера между составными частями приложения, причём части могут и не знать о существовании друг дгуга. Главное, чтоб property существовал иначе будут ошибки. 

qitemdelegate, qt, qtableview, раскраска ячеек

Previous post
Up