QStandardItemModel* from non-GUI thread didn`t emit itemChanged signal
我已经开始使用 QtCuncurrent::run 在非 GUI 线程中加载数据库。
在这个 nonGui 线程中,我必须创建 QStandardItemModel* ,然后我在 GUI 线程中收到模型
1 | model = modelWatcher.result(); |
在 QFutureWatcher finished() 信号上。它工作得很好(UI 已成功构建),但 itemChanged() 信号不会在项目数据更改时发出(复选框状态已更改)。当我在 GUI 线程中创建模型时,没有冲突。没有断言的连接工作失败:
1 2 | bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onFolderStateChanged(QStandardItem*)), static_cast<Qt::ConnectionType>(Qt::UniqueConnection)); Q_ASSERT(ok); |
正如我在那个线程中看到的(没有代码示例,我误解了主要思想)我无法在 nonGui 线程中创建模型(Qt5Gui 的一部分)。但它对我有用! Ui 已构建)我还必须声明发送的类型:
1 | qRegisterMetaType<QStandardItemModel*>("QStandardItemModel*"); |
我的其他发送如下:
1 | qRegisterMetaType<QList<QTreeWidgetItem*> >("QList<QTreeWidgetItem*>"); |
效果很好(尽管它也是 Qt5Gui 的一部分)。
我没有
It
在那种情况下,为什么其他任务在没有任何发射的情况下也能正常工作?包括 currentChanged 信号等。
当我从非Gui线程发送模型时,一些信号丢失了,因为模型指针和相关数据如果我没记错的话是不正确的。还有 QStandardItemModel - 是 Qt5Gui 的一部分,它不是线程安全的。这意味着,模型和视图应该在 GUI 线程中收集,并且数据必须从工作线程发送并绑定到 GUI 线程中的模型。在我的情况下这并不简单 - 我有一棵大树,我不想创建自己的结构来解析树 - 但它是一种"真正的方式")。
我正在使用更简单的决定 - 我只是将 parentItem 指针发送到 GUI 线程中的新模型 - 它可以工作。
如果有人知道如何从简单的工作线程发送树结构 - 请在这个线程中告诉它)
在任何情况下 - 在线程之间使用文本表示的数据传输 - 它更优选的方法(如 JSON/XML...任何你自己的表示,基于项目的索引,列在``QList>` 等......)
你试过这个吗?
1 2 3 | bool ok = connect(model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onFolderStateChanged(QStandardItem*)), static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)); |