PDA

View Full Version : how to color a cell in a QTableView



JeanC
12th January 2008, 10:42
Hello,
I'm gonna try my luck here. On the other forum there are about 20 people asking for this with not much of results.

How can I color a cell in a QTableView?
For instance if the cell holds a '1' I want it blue, else leave it white.

I know I have to override QPaintEvent, but how? I have a pointer to the QTableView that was created in Designer, it's called 'table'.

Now what to do?

In the 'old days' you wrote yourself a paint() function and overwrote the original like table->paint(args) = somefunc. I understand it is not as straightforward in qt.

But please where are working examples for this, I'm getting weary wading through classes and members without much of examples trying to guess things together.
Jean

marcel
12th January 2008, 10:49
You have to subclass QItemDelegate and override its paint method.
In paint you have access to the model index of the cell being painted.

You will have to pass an instance of your delegate when you create the view.

JeanC
13th January 2008, 12:34
Got it working thanks
For those interested my code:

in the .h file add:



class Delegate : public QItemDelegate
{
Q_OBJECT
public:
Delegate(QWidget *parent = 0) : QItemDelegate(parent) {}
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};


in the .cpp, in a constructor



table->setItemDelegate(new Delegate);


and the event:



//---------------------------------------------------
void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QString val;
if (qVariantCanConvert<QString>(index.data()))
val = qVariantValue<QString>(index.data());
if (val == "1")
{
painter->fillRect(option.rect, option.palette.highlight());
}
else
QItemDelegate::paint(painter, option, index);
}

aamer4yu
15th January 2008, 08:53
I was wondering if QTableWidgetItem::setBackground could be of some use in this case ??

one can get the tablewidgetitem(the cell) and set the bacground to it. :confused:

smacchia
30th October 2009, 22:20
Using the delegate works fine if I want to color the text. But I need to color the background of specific cells in the table. I have the following in my delegate:


void MyDelegate::paint(
QPainter *painter,
QStyleOptionViewItem const & option,
QModelIndex const & index) const
{
QStyleOptionViewItem opt(option);

if (index.column() == _colorColumn)
{
opt.palette.setColor(
QPalette::Base,
QColor(255, 255, 204));

opt.palette.setColor(
QPalette::Window,
QColor(255, 255, 204));
}

return QItemDelegate::paint(painter, opt, index);
}


Where _colorColumn is the column that I want the background colored. It's a member variable that gets initialized in the delegate's ctor.

And it's not working. Any ideas what I can do next?

squidge
31st October 2009, 00:01
Wouldn't it be easier to define a model and use Qt::BackgroundColorRole and Qt::TextColorRole in the 'data' method with the default delegate?

Eg.



if (role == Qt::TextColorRole) {
if (index.column() == _colorColumn) {
return Qt::red;
}
}
if (role == Qt::BackgroundColorRole) {
if (index.column() == _colorColumn) {
return Qt::blue;
}
}

sosanjay
31st October 2009, 06:57
Hi,

You can do it simply by using setForeground() for text color and setBackground() for cell background color.

By using

tbl_item = new QTableWidgetItem (QTableWidgetItem (QString (SList.at(0))));
tbl_item->setBackground(QBrush(QColor(Qt::blue)));



I think it is useful for You.

smacchia
2nd November 2009, 15:50
This won't work for me because I'm not use QTableWidget. I'm using QTableView with my own table model.

As I said, changing the color of the text using the QPalette::WindowText works. It's changing the background of the table that isn't taking effect. Neither QPalette::Base or QPalette:Window work.

smacchia
2nd November 2009, 16:10
Wouldn't it be easier to define a model and use Qt::BackgroundColorRole and Qt::TextColorRole in the 'data' method with the default delegate?

Eg.



if (role == Qt::TextColorRole) {
if (index.column() == _colorColumn) {
return Qt::red;
}
}
if (role == Qt::BackgroundColorRole) {
if (index.column() == _colorColumn) {
return Qt::blue;
}
}


I tried this and it also didn't work :(

smacchia
2nd November 2009, 16:51
Well believe it or not I got it to work using the role and the ::data method. However, I had to respond to a role of Qt::BackgroundRole, not Qt::BackgroundColorRole (I figured this out by looking at the Qt source for qitemdelegate.cpp). This is what worked:

if (role == Qt::BackgroundRole && index.column() == _colorColumn)
return QColor(255,255,204);

woodja
15th January 2010, 06:09
I used the QModelIndex's model to color the cell using the setData method that was mentioned above, but as part of slot rather than a delegate. This will highlight whatever cell the user clicks on.


void MyParentWidget::init()
{
connect(((QAbstractItemView*)this->table), SIGNAL(pressed(const QModelIndex&)),
this, SLOT(highlightCell(const QModelIndex&)));
}


void MyParentWidget::highlightCell(const QModelIndex &cellIndex)
{
for(int i=0; i<cellIndex.model()->columnCount(); i++)
{
for(int j=0; j<cellIndex.model()->rowCount(); j++)
{
if(i == cellIndex.column() && j == cellIndex.row())
{
((QStandardItemModel*)cellIndex.model())->item(cellIndex.row(), i)->setData(QBrush(Qt::yellow),
Qt::BackgroundRole);
}
else
{
((QStandardItemModel*)cellIndex.model())->item(cellIndex.row(), i)->setData(QBrush(Qt::white),
Qt::BackgroundRole);
}
}
}
}

You can modify & extend this behavior to meet your needs.

venomj
15th January 2010, 06:53
just overide the data function in your model, it looks like this


QVariant MyTestModel::data(const QModelIndex &index, int role) const
{
switch(role)
{
case Qt::DisplayRole:
return QVariant(QString(tr("%1")).arg((index.column() + 1) * 1000 + index.row() + 1));
case Qt::BackgroundRole:
switch(index.column() % 3)
{
case 0:
return QVariant(QColor(Qt::red));
case 1:
return QVariant(QColor(Qt::green));
case 2:
return QVariant(QColor(Qt::blue));
default://only to disable warning
return QVariant(QColor(Qt::white));
}

break;
default:
return QVariant();
}
}


the BackgroundRole for the item's background color
the ForegroundRole for the text color

SykeS
13th June 2010, 20:10
Reassuming:

How to set font-color to red if value in specified cell is for example not in specified range (int)?

pilpi
9th September 2015, 11:08
Just a sidenote - from a usability point of view, in a majority of cases you probably don't want to paint the entire background.

Screenshot: 11362

In many cases, using a Qt:: DecorationRole is more aesthetic and less obtrusive than filling the entire cell background. The text is still readable; you don't have to think about the contrast between changed foreground and background colours, since DecorationRole only paints a small rectangle of the color you selected, inside the cell.


QVariant MyModel::data(const QModelIndex &index, int role) const
{
int column=index.column();
if((role==Qt::DecorationRole)){
if(column==firstVisibleColumnIndex){
// figure out correct color for current row here
return QColor(100,255,255);
}
}
}