You are not logged in.

1

Thursday, March 11th 2010, 7:40pm

Issues with QTreeWidget

Hi everyone

I am working withr Qt 4.6 (which seems quite buggy), and I would like to know if these errors comes from me, or qt

I would like a qtreewidget, made of children, each children having children. So the design is:

TREE
  • Children 1
    • Sub Children 1
    • Sub Children 2
  • Children 2



Here I have my first issue. I successively tried:

Source code

1
2
3
4
5
6
QTreeWidget* tree = new QTreeWidget(parentwidget); //tree creation
tree->setColumnCount(2); //not the point here but I need it

QTreeWidgetItem* main = new QTreeWidgetItem(tree); //1st level item creation
QTreeWidgetItem* child= new QTreeWidgetItem(main); //2d level item creation, with 'main' as parent
child->setHidden(false); //just to be sure


and

Source code

1
2
3
4
5
6
7
QTreeWidget* tree = new QTreeWidget(parentwidget);
tree->setColumnCount(2); 

QTreeWidgetItem* main = new QTreeWidgetItem(tree); 
QTreeWidgetItem* child= new QTreeWidgetItem(); //2d level creation, without parent
main -> addChild(enfant); //link child->parent
child->setHidden(false);


In both cases, I can't see the items but the 1st leveled one.
However with:

Source code

1
2
3
4
5
6
QTreeWidget* tree = new QTreeWidget(parentwidget);
tree->setColumnCount(2); 

QTreeWidgetItem* main = new QTreeWidgetItem(tree); 
QTreeWidgetItem* child= new QTreeWidgetItem(tree); //child is created as 1st level item
child->setHidden(false);


Of course all items are 1st-level items now (which is not what I want), but at least they all are here!

So FIRST QUESTION:
What is wrong with my ways of including children to the 1st level item?
____________________________________________________________________________________________________________

Then, I am enjoying my all-1st-leveled items. They all are with the design:
[] Name_of_item,
[] being a checkbox.

Then I do:

Source code

1
2
3
4
5
6
7
QTreeWidgetItem* item = new QTreeWidgetItem(tree);
item ->setCheckState(0,Qt::Checked); //to create the column 0 checkbox
item->setText(1,tr("Name")); //to label the ligne

//blablabla do the same for other items

connect( tree , SIGNAL( itemClicked( QTreeWidgetItem*,int ) ), this, SLOT ( updateitem ( QTreeWidgetItem*,int ) ) );


So there, each item looks exactly as I want it to (which is greeeaaaaat). Let's click the first checkbox! Nothing. The second? Nothing. I am a little bit naive ; "Hum, my slot is buggy... Let's add some breakpoints..." The first one I had is right at the first line of the slot function, so if the slot function is read, the breakpoint is hit. Let's run it again. clic. clic. CLIC. CLIC. "SO why are you not hitting my breakpoint?!!!"

So there is my second question:
Why this tree is not clever enough to understand that when I clic on it, I want the itemClicked signal to be emitted?


Is there a way to solve these issues without having to use an older version of qt? I used qtreewidgets just like that with 4.3 and it worked, so what?!

Thanks,
M.

This post has been edited 2 times, last edit by "m3d" (Mar 11th 2010, 8:04pm)


2

Thursday, March 11th 2010, 10:57pm

The problem #1 is solved.
Since problem #2 is a "no answer from widget" issue, I couldn't expand the 1st item, but I can now display its children with setExpanded(true).

Issue #2 is really tricky...

I'll go to 4.7 tomorrow since I don't have answers, Maybe this is a QT issue that would have been solved?
The lack of connectivity is slightly less visible when I add my widget as a central widget instead of as a dock widget: I then can highlight an item which is not possible not....

3

Friday, March 12th 2010, 4:02pm

Actually setExpanded shows ALL children, included the hidden ones... which is not what I want! :(
Someone please help :P

4

Friday, March 12th 2010, 4:17pm

With all these visible hidden children I can see a funny stuff:
Parent item and its 8 first children are not accessible, but the others are.

5

Friday, March 12th 2010, 5:17pm

For the accessible ones, the signal is emitted but the qtreewidgetItem* sent to the slot is NULL.
Any Idea?

BTW, is there anyone reading this?

Junior

Professional

Posts: 1,121

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

6

Friday, March 12th 2010, 7:53pm

Hmmmm, based on the posts I'm not sure how you are creating the parent -> child items, and is there a point when a child item becomes a parent as well. I can help you, but I'm going to need some code as to how your doing this. Or maybe explain what your expecting this to do. I can provided you with a sample to muck with that may be helpful for you in the mean time.

The example will unzip to treewidgetexample dir.
cd into dir.
qmake -project
qmake
make
Junior has attached the following file:

7

Friday, March 12th 2010, 8:51pm

Well, I guess with all these updates it was not clear anymore...



my object is a QMainWindow, and in its constructor I call this function:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
//creation of the dockwidget and its components
QDockWidget* dockWidget = new QDockWidget(tr("Name"),this);
QTreeWidget* tree = createTree(dockWidget);
QWidget* otherwidget = createOtherWidget(dockWidget);

//creation of the design
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(tree);
layout->addWidget(otherwidget);
dockWidget->setLayout(layout);

//finishing
addDockWidget(Qt::RightDockWidgetArea,dockWidget);



the createtree(DockWidget*) function is:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
QTreeWidget* MyMainWindow::createTree(QWidget* parent){

    //creation of the tree and the main item
    QTreeWidget* tree = new QTreeWidget(parent);
    tree->setColumnCount(2);
    QTreeWidgetItem* main = new QTreeWidgetItem(tree);
    main-> setCheckState(0,Qt::Checked);
    main-> setText(1,tr("Gulf"));
    main -> setExpanded(true);

    //loading the children
    for( QList<MyObject>::iterator itr(_myList.begin()); itr!=_myList.end(); ++itr){
   
        QTreeWidgetItem* child = new QTreeWidgetItem();
        child->setCheckState(0,Qt::Checked);
        child->setText(1,itr->name());
        parent->addChild(child);
        child->setHidden(itr->ishidden());

    }//end for

    //do the connect

    connect( tree,	SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
		    this,	SLOT(  updateChild( QTreeWidgetItem*, int ) )
		   );


The issues I have are:

  • I can't click on the parent item nor its 8 first children
  • When I click on a 9-n child, the QTreeWidgetItem* which is loaded at the fist line of my slot is not correct. It as an address, but when I go to 'values' -> [2] -> error(0),error(0). Then my slot is not efficient since I want for instance unchecked the (checked) item but its state is unchecked because of this 'error' field...

This post has been edited 1 times, last edit by "m3d" (Mar 12th 2010, 9:08pm)


8

Friday, March 12th 2010, 9:05pm

Here is what this tree looks like:


I can highlight (and click on) items Child 18, 19 and 20 (and other if there were), but not the previous ones.
If I click on it, an invalid item is sent to the slot:

This post has been edited 1 times, last edit by "m3d" (Mar 12th 2010, 9:18pm)


Junior

Professional

Posts: 1,121

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

9

Saturday, March 13th 2010, 3:20pm

m3d,

Attached is another attempt at getting closer to what I think your trying to do. Let me know if this is in the ball park.

unzips to treewidget1 dir


Junior
Junior has attached the following file:

10

Monday, March 15th 2010, 2:11pm

Typically what you did is to change the way of affectation of the parent item, from:

Source code

1
QTreeWidgetItem* parent = new QTreeWidgetItem* (tree);

to

Source code

1
2
QTreeWidgetItem* parent = new QTreeWidgetItem* ();
tree -> addTopLevelItem(parent);


But actually it changes nothing...


The only difference I can see with your code is that my QWidget is inserted in a QDockWidget... (see lines 7,8,10 and 13 of the first code box in my March 12th 2010, 9:51pm post).
I'll try to insert the widget in the central widget of the QMainWindow, to see if it changes sg...

11

Monday, March 15th 2010, 2:30pm

Ok, then:

  • If I insert the TreeWidget as the centralWidget instead of inserting it inside the DockWidget, I now have access to all the QTreeWidgetItems
  • I hoped the invalid TreeItem* returned by the signal was due by the child level of it, but accessing the top level item leads to the same result
  • If I insert the treewidget directly in the dockwindow with dockWidget::setWidget(tree), it changes nothing
  • If I create a Widget which receive the layout containing my tree and insert it in the dockWidget, NONE of the elements are accessible


I assume now that the tree itself is build and respond correctly, but that there are some issues with the dockwidget...

Junior

Professional

Posts: 1,121

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

12

Monday, March 15th 2010, 8:43pm

m3d,

Just guessing here, but another thing different is your declarations are in the body of functions (constructor and others). Maybe scope is not being friendly here. Have you tried moving the declarations to the header and seeing if that might be causing some grief here.

Contents from ui_mainwindow.h

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
        dockWidget = new QDockWidget(MainWindow);
        dockWidget->setObjectName(QString::fromUtf8("dockWidget"));
        dockWidgetContents = new QWidget();
        dockWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents"));
        verticalLayout = new QVBoxLayout(dockWidgetContents);
        verticalLayout->setContentsMargins(0, 0, 0, 0);
        verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
        treeWidget = new QTreeWidget(dockWidgetContents);
        treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
        treeWidget->setRootIsDecorated(false);

        verticalLayout->addWidget(treeWidget);

        dockWidget->setWidget(dockWidgetContents);
        MainWindow->addDockWidget(static_cast<Qt::DockWidgetArea>(1), dockWidget);
...

One thing above is that the veritcalLayout is constructed with the QWidget as the parent and then the widget is assigned to the dockwidget.

Just a thought.

13

Monday, March 15th 2010, 9:34pm

Well, I was doubtful but tried anyway:

Actually I already tested to declare the widgets in the header OR to create a tampon widget to host the layout, but not the two in the same time.

Then I declared dockWidget and treeWidget in the .h, I added dockWidgetContents (and the setContentsMargins but I doubt this changes anything). I also used static_cast<Qt::DockWidgetArea>(2) instead of Qt::RightDockWidgetArea.

The result is nicely surprising (thanks!), and I now can access all the items of my tree! Another problem solved, thanks!.

However, the second issue is still open:
When I click on one of the items, I enter the slot and have an invalid QTreeWidgetItem* that is returned (see last image posted)...

Junior

Professional

Posts: 1,121

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

14

Monday, March 15th 2010, 10:41pm

Well 1 down and 1 to go...

parent->addChild(child); //??
Shouldn't this be main->addChild(child);

Or are you trying to make this all toplevelItems and just assigning them to separate columns.
Something like this:

Source code

1
2
3
4
5
6
7
QTreeWidgetItem *item = new QTreeWidgetItem();
// for column 0
item->setCheckState(0, Qt::Checked);
item->setText( 0, tr( "Gulf" ));
//for column 1
item->setCheckState( 1, Qt::Checked);
item->setText( 1, tr("Gulf child) );

15

Tuesday, March 16th 2010, 1:51pm

hum yes line 17 is main->addChild, you are right.
Actually all my items (parents or children) appear right now, and with the right design, so it's perfect. The issue is with the connectivity.

When I do:

Source code

1
2
3
connect( tree,	SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
		    this,	SLOT(  updateChild( QTreeWidgetItem*, int ) )
		   );


I am expecting that when I click somewhere on my tree, the signal send QTreeWidgetItem* my_tree_widget_I_click_on and int column_I_click_on to the SLOT. that is what the doc let hope.
But when I click on any item (including the main one, so the issue is not with the toplevelitem/childItems as I hoped), the QTreeWidgetItem which is sent to the SLOT is empty...

Junior

Professional

Posts: 1,121

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

16

Tuesday, March 16th 2010, 1:59pm

Have you tried to move the connect statement out of the function and towards the end of the constructor?

17

Tuesday, March 16th 2010, 5:12pm

I was full of good hope trying your suggestion, but it changes nothing. I still receive invalid pointers.

Actually I was wrong: the pointer sent by the signal is correct. When I do that:

Source code

1
2
3
4
5
6
7
8
9
10
QTreeWidgetItem* main = new QTreeWidgetItem();
	main->setCheckState(0,Qt::Checked);
	main->setText(1,tr("Gulf"));

	if (!loadLayoutsContent())  return 0;

	_tree->addTopLevelItem( main );
	main -> setExpanded(true);
	Qt::CheckState debug_check = main->checkState(0);
	QVariant debug_label = main->data(1,Qt::DisplayRole);
,

what I do just before adding all the children to 'main', actually the 'values' of main are (error) and (error). However debug_check and debug_label are correct. 'main' address is 0x04aed7f8, which seems correct
When I start the slot, the 'values' of main (well, the qtreewidget sent as 'main') are (error) and (error). Its address is 0x04aed7f8 (which means the returned item is the correct one), debug_label is correct but not debug_check.

Now if I am:

Source code

1
2
3
4
5
_dockWidget = new QDockWidget(tr("Layers Manager"),this);
	QWidget* dockWidget = new QWidget();
	createLayers(dockWidget);
	QTreeWidgetItem* main = _tree->topLevelItem(0);
	Qt::CheckState debug_check = main->checkState(0);


the address of main and its checkstate are correct.
I can then track the correct checkstate until the object is created (it is still correct at the last line of the constructor).

Then in my main() I have:

Source code

1
2
3
4
5
6
7
8
    QApplication app( argc, argv );
    QtMapMainWindow mainwindow(0,dialog);
	Qt::CheckState debug_check = mainwindow.test();
	mainwindow.show();
	debug_check = mainwindow.test();
	app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) );
	debug_check = mainwindow.test();
	return app.exec();


(test returns _tree->toplevelitem(0)->checkstate(0) )

the last test still shows a valid status, but I loose it when the signal is emited... :/

18

Tuesday, March 16th 2010, 5:59pm

I made ->setFlags(Qt::ItemIsUserCheckable); on each treeitem and it solved the problem.

Thanks for your help Junior anyway ;)

Junior

Professional

Posts: 1,121

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

19

Tuesday, March 16th 2010, 8:11pm

Source code

1
2
3
4
5
_dockWidget = new QDockWidget(tr("Layers Manager"),this);
	QWidget* dockWidget = new QWidget();
	createLayers(dockWidget);
	QTreeWidgetItem* main = _tree->topLevelItem(0);
	Qt::CheckState debug_check = main->checkState(0);

If this is code inside a function then dockWidget would be deleted after it left the body of the function (not sure if its marked for deletion and released later or the address remains like a null on the heap). The tree would still take ownership of the item. How this would affect the signal/slot I'm not quite sure about without seeing how the moc file constructed it. I doubt that it would affect it. But just something to mention.

It's difficult to debug this without working with your code; The treewidget1 example I posted earlier; I changed it to your way of doing it by adding two columns to the treewidget and then adjusting the items so that the checkbox was in the first column and the text was in the 2nd column. It seemed to work fine with these changes. Admittedly I cannot understand why the contents of the treewidget or connect signal/slot are providing bad results. Maybe you could test all the items in the treewidget after you populate it by looping through them:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for( int i=0; i<treeWidget->topLevelItemCount(); i++ ){
        qDebug() << "parent";
        qDebug() << "chk 1: " << treeWidget->topLevelItem( i )->checkState( 0 );
        qDebug() << "col 1: " << treeWidget->topLevelItem( i )->text( 0 );
        qDebug() << "chk 2: " << treeWidget->topLevelItem( i )->checkState( 1 );
        qDebug() << "col 2: " << treeWidget->topLevelItem( i )->text( 1 );
        for( int j=0; j<treeWidget->topLevelItem( i )->childCount(); j++ ){
            qDebug() << "child";
            qDebug() << "  chk 1: " << treeWidget->topLevelItem( i )->checkState( 0 );
            qDebug() << "  col 1: " << treeWidget->topLevelItem(i)->child(j)->text( 0 );
            qDebug() << "  chk 2: " << treeWidget->topLevelItem( i )->checkState( 1 );
            qDebug() << "  col 2: " << treeWidget->topLevelItem(i)->child(j)->text( 1 );
        }
    }

Junior

Professional

Posts: 1,121

Location: San Antonio, TX USA

Occupation: Senior Secure Systems Engineer

  • Send private message

20

Tuesday, March 16th 2010, 8:12pm

Disregard the last post then.....never mind.... Glad to hear you figured it out.

Similar threads

Rate this thread