PDA

View Full Version : Color the rows in QTableView



grub87
17th June 2009, 15:41
Hi! I'm using a QTableView and want to color the background of the rows, but i can't figure out how. THANKS FOR YOUR HELP!!

spirit
17th June 2009, 15:55
take a look at Qt::BackgroundRole, i.e. you need to set data for a needed item,
you can do it (in general way) as:


...
QModelIndex index = model->index(0, 0);
model->setData(index, Qt::red, Qt::BackgroundRole);
...

estanisgeyer
17th June 2009, 15:57
Hi, subclass the your Model (QSqlQuery for example) and reimplement virtual method data, like this:



QVariant MyModelSqlQryModel::data(const QModelIndex &idx, int role) const
{

QVariant v = QSqlQueryModel::data(idx, role);

if (role == Qt::BackgroundColor)
{
return QVariant(QColor(Qt::yellow));
}

return (v);
}


Marcelo E. Geyer

spirit
17th June 2009, 16:06
here is a compilable example


#include <QtGui>
#include <QApplication>

int main(int argc, char **argv)
{
QApplication app(argc, argv);

QTableWidget table(10, 10);
QAbstractItemModel *model = table.model();
for (int row = 0; row < table.rowCount(); ++row) {
for (int column = 0; column < table.columnCount(); ++column) {
QTableWidgetItem *newItem = new QTableWidgetItem(QObject::tr("%1").arg((row+1)*(column+1)));
table.setItem(row, column, newItem);
const QModelIndex index = model->index(row, column);
model->setData(index, QColor(qrand()%255, qrand()%255, qrand()%255), Qt::BackgroundRole);
}
}
table.show();

return app.exec();
}

grub87
17th June 2009, 16:07
Hi!! I try to put your code in a cycle, so it will color all the tableView, but it didn't work:



int row = 0;
if (query.isActive())
while(query.next()){
QModelIndex index = model->index(row, 1);
model->setData(index, Qt::red, Qt::BackgroundRole);
row++;
}

spirit
17th June 2009, 16:31
if you use some of QSql*Model then you should approach which estanisgeyer suggested of write your own delegate.
an exmaple


class ColorDelegate: public QItemDelegate
{
public:
ColorDelegate(QObject *parent = 0) : QItemDelegate(parent) {}

public:
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
drawBackground(painter, option, index);
QItemDelegate::paint(painter, option, index);
}

protected:
virtual void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
painter->fillRect(option.rect, QColor(qrand()%255, qrand()%255, qrand()%255));
}
};

applying a delegate for a table


...
table->setItemDelegate(new ColorDelegate(table));
...

but in this case when a table is being resized items colors is being changed to.

grub87
17th June 2009, 16:59
Excelent!! thanks!! that get me out of trouble, and i'm also changing the colors of rows like this:



ui.latabladiario->setItemDelegateForRow(0, new ColorDelegate(ui.latabladiario));
ui.latabladiario->setItemDelegateForRow(3, new ColorDelegate(ui.latabladiario));

spirit
17th June 2009, 17:09
add a map or hash to your delegate for keeping color by id (or even better add a proper method in a delegate in which you can pass this map/hash). then you have an index (QModelIndex) using it you can get your id from a table, this should look like this


class ColorDelegate: public QItemDelegate
{
public:
ColorDelegate(QObject *parent = 0) : QItemDelegate(parent) {}

public:
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
drawBackground(painter, option, index);
QItemDelegate::paint(painter, option, index);
}

void setColorMap(const QMap<int, QColor> &colorMap) { m_colorMap = colorMap; }

protected:
virtual void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.column() == 1) {//assume that id keeps in a second column
const int id = index.data().toInt();
painter->fillRect(option.rect, m_colorMap.value(id));
}
}

private:
QMap<int, QColor> m_colorMap;
};

usage


...
ColorDelegate *delegate = new ColorDelegate(&table);
QMap<int, QColor> map;
for (int i = 0; i < 100; ++i)
map.insert(i, QColor(qrand()%255, qrand()%255, qrand()%255));
delegate->setColorMap(map);
table->setItemDelegate(delegate);
...

spirit
17th June 2009, 17:10
Excelent!! thanks!! that get me out of trouble, and i'm also changing the colors of rows like this:



ui.latabladiario->setItemDelegateForRow(0, new ColorDelegate(ui.latabladiario));
ui.latabladiario->setItemDelegateForRow(3, new ColorDelegate(ui.latabladiario));


yup, or like this :)

estanisgeyer
17th June 2009, 17:13
There are several ways to do this, see the example below, if the date is less than the current, applying background color of red.

Example:


QVariant MyModel::data(const QModelIndex &idx, int role) const
{
QVariant v = QSqlQueryModel::data(idx, role);

if ((role == Qt::BackgroundRole) &&
(index(idx.row(), 0, idx.parent()).data().toDate() < QDate::currentDate()))
{
return QVariant(QColor(255, 0, 0));
}

return (v);
}


Marcelo E. Geyer

grub87
17th June 2009, 18:06
This is my final code, i only put in a for cycle to move along the rows:



int polizaInicial = 1;
for (int row = 0; row < numRows; row++) {
const QModelIndex index = model->index(row, 1);
if(index.data().toInt() == polizaInicial){
ui.latabladiario->setItemDelegateForRow(row, new ColorDelegate(ui.latabladiario));
}
else{
polizaInicial++;
}


THANKS!!

luf
17th June 2009, 20:41
You can also use style sheets for selection:
http://doc.trolltech.com/4.5/stylesheet-examples.html#customizing-qtableview

I think background color and color should work as well, but that needs to be tested.