我不知道我的qt代码中是否有错误。我只需要在每次项目数据更改时发出itemChanged
信号。
我使用以下代码来制作模型:
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
- 例如,项目文本已编辑或复选框已单击。
但是在每种情况下,我只在“item1 -...”级别项目(第一级别项目)上触发itemChanged
信号,而不是在第2/3级别项目上。
为什么?我怎样才能使它正确?
PS:QTreeWidget的代码完全相同,但我在我的应用程序中使用多线程,我需要划分模型和视图。无法在非gui线程中创建QTreeWidget项,qtreewidget不能使用自创模型。这就是我必须将QTreeView与QStandardItem一起使用的原因。
答案 0 :(得分: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;
}
}
这意味着,项目需要指向模型的指针以通知模型有关更改,并且子项目的模型设置为插入时父项目 。现在,首先将子项添加到父项,然后将父项添加到父项,将不可见的根作为level-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);
}
}
}
答案 1 :(得分:1)
我不确定为什么默认情况下子项mods没有导致父项被“更改”。我想作为一种解决方法,您可以将每个子节点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()信号对你有用(你的评论建议),那么这应该可行。
修改强>
啊,我认为这可能实际上并不像你想要的那样。我想你总会得到一个发送到你的onChanged()插槽的item1指针。如果你想发送item3指针,那么你可能需要子类QStandardItem(创建一个继承QStandardItem的类),然后执行以下操作:
itemChanged(QStandardItem*)
void itemHasChanged() {emit itemChanged(this);}
然后在你的循环中你可以item1 = new myQStandardItem;
然后为您添加的每个新项目直接将它们连接到您的onChanged()插槽:
QObject::connect(itemX, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onChanged(QStandardItem*)));
如果你不能让模型为你做这个(即计划-B),这是一个额外的努力(但不是太多)......