PDA

View Full Version : QTreeWidget's Item Widgets



jpn
9th February 2006, 20:43
I might have found a bug in Qt 4.1.

QTreeWidget::setItemWidget(), which was introduced in Qt 4.1 allows a widget to be displayed in an tree item's cell.

An example code below creates a simple QTreeWidget with 10 rows and 2 columns.
The first column contains item's index as text and the second column contains a QLabel with same text, respectively.



QTreeWidget* tree = new QTreeWidget;
tree->setColumnCount(2);

for (int i = 0; i < 10; ++i) {
QTreeWidgetItem* item = new QTreeWidgetItem;
item->setText(0, QString::number(i));
tree->addTopLevelItem(item);
tree->setItemWidget(item, 1, new QLabel(QString::number(i)));
}


Resizing the QTreeWidget small enough to get the vertical scrollbar visible and then scrolling back and forth messes up the item widget drawing in the second column. Though, resize event seems to fix the erroneous drawing.

http://www.uusikaupunki.fi/~jpnurmi/QTreeWidget_1.JPG
http://www.uusikaupunki.fi/~jpnurmi/QTreeWidget_2.JPG

- JP

wysota
9th February 2006, 21:29
You forgot to add the second image.

jpn
10th February 2006, 06:39
Second image fixed.

wysota
10th February 2006, 09:10
So what is wrong with that widget? It looks fine...

jacek
10th February 2006, 09:37
So what is wrong with that widget? It looks fine...
Look at the code --- numbers in both columns should be the same.

wysota
10th February 2006, 09:39
They are not the same even in the first picture...

I thought the display was being cluttered, but it looks like the issue is different

jpn
10th February 2006, 09:44
1) Here it is shown correctly:

http://www.uusikaupunki.fi/~jpnurmi/QTreeWidget_3.JPG

2) After resizing and then scrolling back and forth it becomes messed:

http://www.uusikaupunki.fi/~jpnurmi/QTreeWidget_4.JPG

3) Resizing again fixes the drawing:

http://www.uusikaupunki.fi/~jpnurmi/QTreeWidget_5.JPG

Above screenshots are taken in WinXP SP2.


Same malfunction detected also in KDE 3.4.3:

http://www.uusikaupunki.fi/~jpnurmi/snapshot1.png

jacek
10th February 2006, 17:00
I've just checked on my system (PLD Linux, Qt 4.1.0) and it also doesn't work the way it should.

Here is the full example:
#include <QApplication>
#include <QLabel>
#include <QTreeWidget>

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

QTreeWidget* tree = new QTreeWidget;
tree->setColumnCount(2);

for (int i = 0; i < 10; ++i) {
QTreeWidgetItem* item = new QTreeWidgetItem;
item->setText(0, QString::number(i));
tree->addTopLevelItem(item);
tree->setItemWidget(item, 1, new QLabel(QString::number(i)));
}

tree->show();

return app.exec();
}

@jpn: Did you try the latest snapshot?

wysota
10th February 2006, 18:54
This is my system (compiled Qt4.1), also not correct:

jpn
10th February 2006, 19:12
Alright, I grabbed the snapshot from yesterday (4.1.1-20060209). The original bug seems to have already been fixed. Despite of scrolling, all item widgets are always drawn in correct positions. Keep up the great work, Trolltech!

Nevertheless, another cosmetic issue related to this appeared. Selecting rows seems to mess up the item widget drawing too (especially QLabel, as in this case). The following image explains this another cosmetic bug(?):

http://www.uusikaupunki.fi/~jpnurmi/QTreeWidget_selection.jpg
Rows 2,4,6 have each been selected before selecting row 8.

(WinXP+SP2 / Qt-4.1.1-snapshot-20060209)

jpn
1st April 2006, 21:17
Just for your information..

The reason for this problem is that QLabel has the autoFillBackground set to false by default.
This means that you will see both the item and the label contents. Setting autoFillBackground to true fixes this problem.
Task Tracker - Entry 103100 (http://www.trolltech.com/developer/tasktracker.html?id=103100&method=entry)

jpn
1st April 2006, 23:56
I'd claim this does not FIX the problem, this method only covers it.
It really is interesting why does the QTreeView draw the contents of the label.

The rejecting reason says "you will see both the item and the label contents"..
But the items in the second column should be empty. There has been set text only
for the items in the first column, and a label widget for the items in the second column!

Besides, forcing the QLabel to fill it's background also naturally overrides the selection drawing.

I managed to find something very interesting by accident:

#include <QtGui>
int main( int argc, char **argv )
{
QApplication app(argc,argv);
QTreeWidget* tree = new QTreeWidget;
tree->setColumnCount(1);
for (int i = 0; i < 10; ++i)
{
QTreeWidgetItem* item = new QTreeWidgetItem(tree);
QWidget* widget = new QWidget;
tree->setItemWidget(item, 0, widget);
}
tree->show();
return app.exec();
}

The above code is a dummy example showing an "empty" tree with widgets.
The funny thing is, when you click items, there is an output like this:

QWidget::property("text") failed: property invalid or does not exist
QWidget::setProperty("text", value) failed: property invalid, read-only or does not exist

So clearly the text-property of a widget is requested.
I took a look at the Qt sources, and I found that it's QItemDelegate::setModelData() which requests this property.

As for a test, I subclassed QItemDelegate and overrode setData() by an empty mplementation body.
Voila! The QLabel gets drawn correctly in a QTreeWidget. Or more correctly the item does not draw the label contents. Quite an ugly workaround, that is.. :)

I guess I'll have to bug the Trolls, maybe there is a solution out there..