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,
раскраска ячеек