Some problems with checkbox checking in QTreeView/QTreeWidget (signal itemChanged())
-
Hi!
I have some questions about Tree widgets:
In my program I had QTreeWidget and it works fine. But I need multithreading in my app, because UI is lag when app processing data`s.
Is there any way to send "model" data from "data" thread to "UI" thread? Or I only can create class in data thread and fill it with data and then send data to UI thread to build QTreeWidget items from it?
However, now I already use QTreeView with MVC template.
Ok, I create model with following code:QStandardItemModel* model = new QStandardItemModel; QStandardItem* parentItem = model->invisibleRootItem(); QList<QStandardItem*> itemList1; QList<QStandardItem*> itemList2; QList<QStandardItem*> itemList3; QStandardItem* item1 =new QStandardItem; QStandardItem* item2 =new QStandardItem; QStandardItem* item3 =new QStandardItem; for(;;) { // example item1 = new QStandardItem(item->Text)); item1->setFlags(item1->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); item1->setCheckState(Qt::Unchecked); item1->setCheckable(true); for(;;) { item2 =new QStandardItem(LPCWSTR2QString(folder->Text)); item2->setFlags(item2->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); item2->setCheckState(Qt::Unchecked); for(;;) { // creates item3 and : item2->appendRows(itemList3); itemList3.clear(); } item2->appendRows(itemList3); itemList3.clear(); } itemList2 << item2; } itemList1 << item1; } parentItem->appendRows(itemList1); // itemList2 and 3 .. itemList1.clear();
this model looks like what I want.
But my code that worked with QTreeWidget (with some changes) don`t work with QTreeView:void test::onItemChanged(QStandardItem *item) { if ( !item->isCheckable() || item->column() != 0 ) return; Qt::CheckState state = item->checkState(); if ( state == Qt::Checked || state == Qt::Unchecked ) { for ( int i = 0; i < item->rowCount(); i++ ) { QStandardItem* child = item->child(i); if ( child->isCheckable() && child->checkState() != state ) child->setCheckState(state); } } QStandardItem* parent = item->parent(); if ( parent && parent->isCheckable() ) { state = parent->child(0)->checkState(); if ( state == Qt::PartiallyChecked ) parent->setCheckState( state ); else { int i = 1; while ( i < parent->rowCount() && parent->child(i)->checkState() == state ) i++; if ( i != parent->rowCount() ) state = Qt::PartiallyChecked; parent->setCheckState( state ); } } } // call from: QStandardItemModel* model = readModel(); bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onItemChanged(QStandardItem*))); Q_ASSERT(ok); updateUI(model); // [](){ui.treeView->setModel(model)}
I don't know why itemChanged, that must emit on every time that data of item changed (checkbox state changed) - emitted only when level1 item checked/unchecked or level1 items expanded/collapsed.
It happens because I creates 2nd and 3rd level items with parent.appendRows(itemLevel2etc)?
If it is, which way I need to create this items and which way to process qtreeview with checkboxes is valid?
Thx a lot) -
You should never use Qt UI classes outside the GUI thread! They are not thread safe!
Your other threads should send the data to the GUI thread (for example via signals) and in the GUI thread you then can do what ever needs to be done with the data.