views:

1400

answers:

6

I'm trying to make the cells of a QTableView look like 3D clickable buttons. So that when you click on a cell, the button looks pushed. Everyone seems to think I merely want to change the colour, I need to show images of a normal button, and a pushed button, that look 3-dimensional.

I have done this already with calling QTableView::setItemDelegate(), with an appropriate ItemDelegate that will change the background of the cell when it's clicked. However I'm stuck at this point because I want some cells to be different coloured buttons based on the data they contain. So a cell with a low number would be a red button, that's also red when it's clicked, and the other cells would be different colours.

I can set the colour of the button with the TableModel, but once the button is clicked, there is no way for the ItemDelegate to know that it's supposed to be a different colour than the rest. How can you link the two so the ItemDelegate knows what colour it's supposed to be?

Also, is there simply a better way to make cells look like buttons?

A: 

Can you not get the ID/row count of the table cell's row and then check it against the colour table that you may be having, and set the colour accordingly? I am not sure if I understood your question well or not.

Alan Haggai Alavi
Yeah I thought of that, but you'd have to have a separate colour table which isn't so elegant. I'm looking for a better way.
Neil
Also I need button images, not colours. There is no way to set the button image and have it all work like it does with colours.
Neil
+1  A: 

You can call QModelIndex::model() from within the ItemDelegate's paint() method, since it has a QModelIndex parameter. This gives you the TableModel for the data, which you can programatically decide what colour the cell's button will be.

However, this is still not as elegant as I'd hope. Does anyone know a better way to change the appearance of table cells when in both the up and down button push states?

Neil
Just figured this out right after asking the question.
Neil
A: 

Assign a data role for the background color, and in your item delegate, ask the model index what it's background color is (using data( bg_color_role ) or something similar). Then, in your model, you need to make sure the data function returns a color for the bg_color_role that is appropriate for the data being modeled.

Caleb Huitt - cjhuitt
Can you do this with images? I need to set a 3D button image for both down and up states for the cell.
Neil
A: 

Why don't you asked the index for the background color.

Something like this ...

QStyleOptionToolButton buttonOption;
const QStyleOptionViewItemV4& optionV4 = dynamic_cast<QStyleOptionViewItemV4&>(option);
//...
buttonOption.palette.setBrush( QPalette::Button, index.data( Qt::BackgroundColorRole ) ); 
//...

I have feeling that its a bug in Qt and its must have been ...

// model code  
if(role==Qt::BackgroundColorRole )
    return qvariant_cast<QBrush>( QBrush(Qt::red) );

// delegate code 
buttonOption.palette.setBrush(QPalette::Button, optionV4.backgroundBrush );

Because the optionV4.backgroundBrush is correct in the sizeHint method but is invalid in the paint method . I see now reason why the sizeHint should have the background brush and the paint method not. I'll report it to Nokia.

EDIT:

Looks like I was right and its a bug in < Qt4.5.
QStyleOptionViewItemV4 doesn't copy the icon and backgroundBrush

TimW
I need to do this with up and down state images, not just background colours.
Neil
maybe you can use the Qt::CheckStateRole role for this.
TimW
A: 

The way to do that is to use the data method of the QModelIndex object you get on the paint method, and ask for a specific role (if you define a custom model, you can add your own roles, and give the information you need to the delegate in those roles.)

TimW, I think you have to fill the QStyleOptionViewItemV4 info by calling initStyleOption before.

Federico
Is there a background image role for mouse down and mouse up events? I need to make the table cells behave like a 3D button.
Neil
I think that you can use the state flag of the QStyleOptionViewItem to check if the item was pressed (there is QStyle::State_Sunken value). And together with that you can use the QStyleOptionButton to do the drawing
Federico
A: 

I'm not sure where the requirement for a background image comes from. If you want the cells to look like QPushButtons, you should probably inherit from QItemDelegate and implement paint() to use QStyle to draw you a QPushButton, something like this:

QStyleOptionButton opt;
// fill 'opt' from the information from the model, and the style option that's passed in
style()->drawControl( QStyle::CE_PushButton, &opt, painter );