PDA

View Full Version : Alternate row colours in QFormLayout



xtal256
30th January 2011, 21:53
Is there a way to do this in a form layout? I know you can do this in a list view, but my UI needs to layout more complex widgets in rows. I want each row to alternate between two colours.

I don't think it is possible to set the background colour of each "row", but i could be wrong. And i could set the colour of each individual widget (the QFormLayout::LabelRole one and the QFormLayout::FieldRole one), but they do not always fill the entire area (e.g. a label is only as big as the text it contains).

If there was some way i could do it with stylesheets, that would be awesome.

xtal256
1st February 2011, 23:09
anyone?

If anyone wants to know what i am talking about, here is a mockup of what i want:
http://img141.imageshack.us/img141/1417/formq.png

The labels are QLabel objects and the fields are QLineEdit, QTextEdit, or any other widget i need.

Lykurg
2nd February 2011, 06:12
I am not aware of such a feature, since QLayout's are for positioning the items and not for drawing at all. But regarding your screen shot, you could use QTableWidget which has the alternating feature and with its cellWidget you can set complex widgets to it.

thec0der
2nd February 2011, 09:52
Last night I try do this, unfortunately there is something that I don't know how to do (may be you will find a way :)).
What is the idea -
When call class constructor for your window, call findChildren and get the list of all your QHBoxLayouts.
Iterate through it, and collect its dimensions and locations (I'm able to get the dimension, but I was unable to find its position).
Override paint event of your window, draw on odd or even count, a bars with specified color.

xtal256
2nd February 2011, 21:56
I am not aware of such a feature, since QLayout's are for positioning the items and not for drawing at all. But regarding your screen shot, you could use QTableWidget which has the alternating feature and with its cellWidget you can set complex widgets to it.

A table widget was what i first thought of, and being able to set any arbitrary widget in it's cells is helpfull. But unfortunately i want a more complex UI than just a table. I should have mentioned this earlier, but for some rows i am planning on using a single widget with QFormLayout::SpanningRole. A table would probably not allow me to do this.

I think the only way i am going to be able to do alternate rows is to set the background colour of each widget specifically. But as i mentioned in my first post, label widgets and other widgets do not resize to fill the area where they are in the layout. So i may have to write some tricky code to lay them out the way i want. Or do some custom drawing like thec0der suggested.

Lykurg
2nd February 2011, 22:02
Even if that is surely not the best solution, you can use QTableView::setSpan() also on a QTableWidget. But be clear, that you are abusing QTableWidget!

xtal256
4th February 2011, 23:20
Yeah, i think i will just use a form layout since it seems like the nicest way. I will worry about colouring rows later.

xtal256
16th February 2011, 04:32
Hi again.

After sorting out other problems, i have started looking at this again.

I figure if i can get each widgets to fill it's whole area of the form, then i can set it's background colour and should be able to get the look i am going for.
I was playing around with the size policy of the QLabel widgets (in the FieldRole) and found that i can get their vertical size to expand as far as the form layout will allow, but the same is not true for the horizontal size. For example, in the screenshot i posted earlier, the "Multiple Lines" label would be as high as it's counterpart widget, but it would not be as wide as the other labels. So each of their widths would be different.

I am wondering if there is any easy way to get this to work. One way would be to calculate their widths myself, based on the widest one. But that may be tricky with the form layout automatically sizing them to fit.

xtal256
17th February 2011, 22:48
Anyone able to help?

xtal256
27th February 2011, 22:36
Hi again,

I have solved my problem, and noticing how this post comes up in google, i thought i'd post my solution for future coders to use :)

Basically, what i did was override the paint event and calculate the vertical offset to draw each row:

/*------------------------------------------------------------------+
| Custom paint event to draw alternate row colours. |
+------------------------------------------------------------------*/
void AbstractPropertyPage::paintEvent(QPaintEvent*) {
QPainter painter(this);
painter.setPen(Qt::NoPen);

// Fill the entire background with even colour first, then draw odd
// rectangles. Probably more efficient this way
painter.setBrush(evenRowColourProperty);
painter.drawRect(0, 0, this->width(), this->height());

// This could be more... elegant
int y = margin - (spacing / 2);
bool alt = false;
painter.setBrush(oddRowColourProperty);
for (int i = 0; i < formLayout->rowCount(); i++) {
QLayoutItem* item = formLayout->itemAt(i, QFormLayout::FieldRole);
if (item) {
int h = item->sizeHint().height() + spacing;
if (alt) {
painter.drawRect(0, y, this->width(), h);
}
y += h;
alt = !alt;
}
else {
item = formLayout->itemAt(i, QFormLayout::SpanningRole);
if (item) {
int h = item->sizeHint().height() + spacing;
if (alt) {
painter.drawRect(0, y, this->width(), h);
}
y += h;
alt = !alt;
}
}
}
}

I'm figured i needed the check for FieldRole and SpanningRole since i use both layouts in my form, but some quick debugging showed that the SpanningRole branch was never being entered even when i had some widgets using that role. Anyway, it all seems to work, so i'm happy.