2016-06-12 11 views
2

私のQtコードに何か問題があるかどうかわかりません。私は、項目データが変更されるたびにitemChangedシグナルが放出されることを必要としています。例えば、項目のテキストを編集またはチェックボックスがクリックされた - onChangedはアイテムが変更されるたびに呼び出されますことを、Qt item QTreeViewモデルの変更された信号は、最初のレベルの項目でのみ動作します

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*))); 

と私がしたい: 私はモデルを作るために、次のコードを使用します。 いずれの場合も、私はitemChanged信号を "item1 -..."レベル項目(第1レベル項目)のみでトリガーし、item2/3レベル項目ではトリガーしませんでした。 なぜですか?そして、それをどうすれば正しいことができますか?

PS:QTreeWidgetと同じコードは完璧に動作しますが、私は自分のアプリでマルチスレッドを使用しており、モデルとビューを分割する必要があります。 qTreeWidget項目は非GUIスレッドでは作成できません。qtreewidgetは自己作成モデルを使用できません。それがQStandardItemでQTreeViewを使用する必要がある理由です。

答えて

3

私は状況をデバッグし、あなたが信号を得ることはありません理由は、アイテムのデータが変更された場合、あなたはQtのソースでこれを持っている。一方

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

、親に子アイテムを追加するとき、あなたは

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

を持っているので、これは意味し、項目が変更についてのモデルを通知するモデルへのポインタを必要とし、子アイテムのモデルは、親のに設定されています項目を挿入時にします。今度は、子を最初に親に追加し、次に親を親に追加します。不可視のルートをレベル1のアイテムの親として追加します。不可視ルートにはモデルがあるため、レベル1のアイテムは信号を送信しますが、他のアイテムは送信しません。

簡単な変更の修正この:ちょうど最初の親に項目を追加し、子供を追加し、このような:

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

それは動作しますが、THX)私はトラブルがツリー構築法であることを示唆したが、あなたはそれを明確かつ単純にする) –

1

デフォルトでは、子アイテムの改造が親アイテムを「変更」させない理由はわかりません。何が起こる必要があることは、あなたが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; 
      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; 
} 

:私は、信号が階層を伝播するようあなたは、その親DataChanged()信号にそれぞれチャイルズDataChanged()信号を接続することができ、回避策としてのようなものを想定します信号はITEM1までのすべての方法を転送(あなたが働いている示唆している)、その後、通常通り継続する必要があります:私はこれをテストしていません

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

が、ITEM1 dataChanged()信号が(あなたのために働いていると仮定していますあなたのコメントが示唆している)、これはうまくいくはずです

編集

ああ、私はあなたがそれをしたいと、これは実際に動作しないかもしれないと思います。私はあなたのonChanged()スロットに送信されたitem1ポインタを取得すると思います。あなたが送信されITEM3ポインタをしたいなら、あなたは、サブクラスQStandardItemする必要があります(QStandardItemを継承するクラスを作る)して、次の操作を行います

  • が発する信号を追加します。itemChanged(QStandardItem*)
  • は、スロットを追加します。void itemHasChanged() {emit itemChanged(this);}
  • コンストラクタでdataChanged()をitemHasChanged()に接続します。

次に、あなたのループの中であなたがitem1 = new myQStandardItem; そしてあなたが直接追加し、それぞれの新しい項目のためにあなたのonChangedイベントにそれらを接続することができます()スロット:

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

は、それは(ただし、あまりにも余分な労力のビットですあなたがモデルをあなたのためにやることができないのならば(例えば、プランB)...次のように

関連する問題