2016-06-12 23 views
2

Я не знаю, что-то не так в моем коде qt. Мне просто нужно, чтобы сигнал itemChanged излучался каждый раз при изменении данных элемента. Я использую следующий код, чтобы сделать модель:Qt itemChanged сигнал с моделью 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*))); 

и я хочу, что onChanged будет вызываться каждый раз, когда пункт изменен - ​​например, текст элемента изменен или флажок щелкнул. Но в каждом случае я активировал сигнал itemChanged только на элементах уровня «item1 -...» (элементы первого уровня), а не на элементах уровня item2/3. Почему? И как я могу сделать это правильно?

PS: тот же код с QTreeWidget работает отлично, но я использую многопоточность в своем приложении, и мне нужно разделить модель и просмотр. Элементы QTreeWidget не могут быть созданы в потоке non-gui, а qtreewidget не может использовать самосозданную модель. Вот почему я должен использовать QTreeView с QStandardItem.

ответ

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

Он работает, ТНХ) я предположил, что беда была в хлыстов здания, но вы делаете это ясно и просто) –

1

Я не уверен, почему по умолчанию для модов дочерних элементов не возникает «изменение» родительского элемента. Я полагаю, в качестве временного решения можно подключить каждый из Чайлдса DataChanged() сигнала своих родителей DataChanged() сигнала, так что сигнал распространяется вверх по иерархии, что-то вроде:

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; 
} 

Что должно произойти в том, что если вы измените запись уровня item3 сигнал должен быть направлен весь путь до item1 (который вы предлагаете работает), а затем продолжится в обычном режиме:

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

Я не проверял, но если предположить, сигнал item1 dataChanged() работает для вас (который ваши комментарии предполагают), тогда это должно сработать.

Редактировать

Ах, я думаю, что это не может реально работать, как вы хотите. Я думаю, вы всегда получите указатель item1, посланный в ваш слот onChanged(). Если вы хотите, чтобы указатель 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) ...

 Смежные вопросы

  • Нет связанных вопросов^_^