2016-06-12 4 views
2

Ich weiß nicht, ob ich etwas falsch in meinem QT-Code. Ich brauche nur, dass das Signal itemChanged jedes Mal ausgegeben wird, wenn sich die Daten geändert haben. ich folgenden Code verwenden, um das Modell zu machen:Qt itemChanged Signal mit QTreeView-Modell funktioniert nur auf der ersten Ebene Elemente

QStandardItemModel* model = new QStandardItemModel; 
QStandardItem *parentItem = model->invisibleRootItem(); 
QList<QStandardItem*> itemList1; 
QList<QStandardItem*> itemList2; 
QList<QStandardItem*> itemList3; 
QStandardItem* item1; 
QStandardItem* item2; 
QStandardItem* item3; 

for (int i = 0; i < 3; ++i) 
{ 
    item1 = new QStandardItem; 
    item1->setText("item1-" + QString::number(i)); 

    for (int i = 0; i < 3; ++i) 
    { 
     item2 = new QStandardItem; 
     item2->setText("item2-" + QString::number(i)); 

     for (int i = 0; i < 3; ++i) 
     { 
      item3 = new QStandardItem; 
      item3->setText("item3-" + QString::number(i)); 
      itemList3 << item3; 
     } 
     item2->appendRows(itemList3); 
     itemList3.clear(); 
     itemList2 << item2; 
    } 
    item1->appendRows(itemList2); 
    itemList2.clear(); 
    itemList1 << item1; 
} 
parentItem->appendRows(itemList1); 
itemList1.clear(); 

ui.treeView->setModel(model); 

QObject::connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onChanged(QStandardItem*))); 

und ich möchte, dass onChanged wird jedes Mal aufgerufen, wenn Element geändert - zum Beispiel Itemtext bearbeitet oder Checkbox angeklickt. Aber in jedem Fall habe ich itemChanged Signal nur auf "item1 -..." Ebene Elemente (erste Ebene Elemente), nicht auf Element2/3 Ebene Elemente ausgelöst. Warum? Und wie kann ich es richtig machen?

PS: Derselbe Code mit QTreeWidget funktioniert perfekt, aber ich benutze Multithreading in meiner App und ich muss Modell und Ansicht teilen. QTreeWidget-Elemente können nicht in Nicht-GUI-Threads erstellt werden, und qtreewidget kann das selbst erstellte Modell nicht verwenden. Aus diesem Grund muss ich QTreeView mit QStandardItem verwenden.

Antwort

3

ich debuggt nur die Situation, den Grund, warum Sie nicht bekommen das Signal ist wie folgt: Wenn die Daten des Elements geändert wird, müssen Sie dies in der Qt Quelle:

void QStandardItem::setData(...) 
{ 
    /* ... */ 
    if (d->model) 
     d->model->d_func()->itemChanged(this); 
} 

Auf der anderen Seite wenn ein Kind Element an einen Elternteil hinzufügen, haben Sie

bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &items) 
{ 
    /* ... */ 
    for (int i = 0; i < items.count(); ++i) { 
    /* ... */ 
     item->d_func()->model = model; 
    } 
} 

dies bedeutet also, Einzelteile benötigen einen Zeiger auf das Modell, das Modell über die Änderung zu informieren, und das Modell eines Kindes Artikel wird auf die Eltern gesetzt Artikel zum Zeitpunkt der Einführung. Jetzt fügst du die Kinder zuerst dem Elternteil und dann den Eltern zu ihren Eltern hinzu, mit der unsichtbaren Wurzel als Elternteil der Gegenstände der Stufe 1. Da die unsichtbare Wurzel ein Modell hat, senden die Elemente der Ebene 1 das Signal, die anderen jedoch nicht.

Eine einfache Änderung korrigiert diese Fehler: Gerade das Element zu seiner Mutter hinzufügen zuerst, und dann die Kinder anhängen, wie folgt aus:

for (int i = 0; i < 3; ++i) 
{ 
    item1 = new QStandardItem; 
    item1->setText("item1-" + QString::number(i)); 
    parentItem->appendRow(item1); 

    for (int i = 0; i < 3; ++i) 
    { 
     item2 = new QStandardItem; 
     item2->setText("item2-" + QString::number(i)); 
     item1->appendRow(item2); 

     for (int i = 0; i < 3; ++i) 
     { 
      item3 = new QStandardItem; 
      item3->setText("item3-" + QString::number(i)); 
      item2->appendRow(item3); 
     } 
    } 
} 
+0

Es funktioniert, thx) Ich schlug vor, dass Probleme in der Baum Bauweise war, aber du machst es klar und einfach) –

1

Ich bin mir nicht sicher, warum der Standard für untergeordnete Artikelmodifikationen ist, die nicht bewirken, dass der übergeordnete Artikel "geändert" wird. Ich nehme an, wie dieses Problem zu umgehen Sie könnte jedes Kindes DataChanged() Signal an seinen Eltern DataChanged() Signal verbinden, so dass das Signal in der Hierarchie ausbreitet oben, so etwas wie:

for (int i = 0; i < 3; ++i) 
{ 
    item1 = new QStandardItem; 
    item1->setText("item1-" + QString::number(i)); 

    for (int i = 0; i < 3; ++i) 
    { 
     item2 = new QStandardItem; 
     item2->setText("item2-" + QString::number(i)); 

     for (int i = 0; i < 3; ++i) 
     { 
      item3 = new QStandardItem; 
      item3->setText("item3-" + QString::number(i)); 
      itemList3 << item3; 
      connect(item3, SIGNAL(DataChanged()), item2, SIGNAL(DataChanged())); 
     } 
     item2->appendRows(itemList3); 
     itemList3.clear(); 
     itemList2 << item2; 
     connect(item2, SIGNAL(DataChanged()), item1, SIGNAL(DataChanged())); 
    } 
    item1->appendRows(itemList2); 
    itemList2.clear(); 
    itemList1 << item1; 
} 

Was geschehen sollte, ist, dass, wenn Sie einen item3 Ebene Satz ändern die Signal sollte den ganzen Weg bis zu item1 weitergeleitet werden (die Sie vorschlagen arbeitet) und dann ganz normal weiter:

item3 ---DataChanged()---> item2 
item2 ---DataChanged()---> item1 
item1 ---DataChanged()---> model 
model ---itemChanged()---> onChanged() 

ich nicht getestet, aber vorausgesetzt, die item1 datachanged() Signal für Sie arbeitet (die Ihre Kommentare suggerieren), dann sollte das funktionieren.

bearbeiten

Ah, ich denke, das, wie Sie es wollen, nicht wirklich funktionieren kann. Ich denke, Sie werden immer einen Zeiger auf den Point1 zu Ihrem onChanged() - Slot gesendet bekommen. Wenn Sie den item3 Zeiger gesendet werden soll, dann können Sie zu Unterklasse QStandardItem haben (eine Klasse machen, die QStandardItem erbt) und dann wie folgt vorgehen:

  • ein Signal hinzufügen, die emittiert: itemChanged(QStandardItem*)
  • einen Schlitz hinzufügen: void itemHasChanged() {emit itemChanged(this);}
  • Verbinden Sie DataChanged() mit ItemHasChanged() im Konstruktor.

Dann in der Schleife können Sie item1 = new myQStandardItem; Und dann für jedes neue Element, das Sie direkt in Ihre onChanged hinzufügen connect() Slot:

QObject::connect(itemX, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onChanged(QStandardItem*))); 

Es ist ein bisschen von einem zusätzlichen Aufwand (aber nicht zu viel), wenn Sie das Modell nicht dazu bringen können, es für Sie zu tun (zB einen Plan-B) ...

Verwandte Themen