QTreeView模型的Qt-itemChanged信号仅适用于一级项目
Qt itemChanged signal with QTreeView model works only on first level items
我不知道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
,例如,编辑项目文本或单击复选框。但在每种情况下,我只在"项目1-…"级项目(一级项目)上触发了itemChanged
信号,而不是在项目2/3级项目上。为什么?我该如何纠正?
附言:QTreeWidget的相同代码运行得很好,但我在应用程序中使用了多线程,我需要划分模型和视图。QTreeWidget项目不能在非gui线程中创建,QTreeWidget不能使用自己创建的模型。这就是为什么我必须将QTreeView与QStandardItem一起使用的原因。
我刚刚调试了这个情况,你没有得到信号的原因如下:当项目的数据更改时,你在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;
}
}
因此,这意味着,项需要一个指向模型的指针来通知模型更改,并且子项的模型在插入时被设置为父项。现在,先将子项添加到父项,然后将父项添加到其父项,其中不可见的根作为一级项目的父项。由于不可见的根有一个模型,一级项目发送信号,但其他项目不发送。
一个简单的更改修复了这个问题:只需先将项添加到其父项,然后附加子项,如下所示:
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);
}
}
}
我不知道为什么默认情况是子项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;
}
应该发生的是,如果你改变了项目3级别的记录,信号应该一直转发到项目1(你认为它正在工作),然后继续正常:
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计划),这需要一点额外的努力(但不会太多)。。。
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法在 CLion 中构建 C++ 项目
- 运行同一解决方案的另一个项目的项目
- CMake-按正确顺序将项目与C运行时对象文件链接
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 欧拉项目#8答案是大以获得有效答案
- 从链接列表c++中删除一个项目
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 既然存在危险,为什么项目要使用-I include开关
- cmake在我的项目中所需的所有静态库都不成功
- QT通过C++添加映射QML项目
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 在linux上调试巨大的C++项目
- 在其他文件中创建类时在 c++ 项目中不起作用
- 使外部项目可用于find_package CMake
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- 使用外部SDK工具链文件在VisualStudio上生成项目编译错误
- 如何维护资源管理器项目视图中当前可见的项目列表
- 错误-我无法在VS2019中打开新的Qt项目
- QTreeView模型的Qt-itemChanged信号仅适用于一级项目