ListView中没有更新

Ans*_*mar 7 qt listview qthread qtquick2

我创建了一个派生自QAbstractListModel并重新实现所有必要功能的类.我创建了一个对象,将一些初始数据填入模型(所有beginInsertRows等完成),然后将它(对象)传递给qml via setContextProperty.我正在使用QQuickView.一旦qml被show()命令显示,我产生一个QThread我使用Model对象的指针.线程通过直接调用Model的addData(..)函数(具有beginInsertRowsetc)继续向模型添加数据.

问题:没有UI的更新.我在QtCreator的"应用程序输出"窗格中列出了以下内容:

QObject::connect: Cannot queue arguments of type 'QQmlChangeSet'
(Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().)
Run Code Online (Sandbox Code Playgroud)

这里的表格显示了完全相同的问题,但我不能使用那里提到的信号和插槽.

编辑:

从主线程运行addData()(使用链接中提到的信号槽但不是子类QThread)确实将ListView更新为初始数据,但是在dataChanged()信号之后视图没有更新.让我更清楚地解释一下.

/*This is the class in which data is stored*/
class ClientCardModel : public QAbstractListModel {
    ....
    QList<ClientCard*> m_list;
};

...
ClientCardModel hand;    // object to send to qml

...     
 // New worker thread created and all the following codes are exexuted in that
 QThread *workerThread = new QThread; 

/*New data is created to be inserted in model*/
ClientCard* ccard = new ClientCard;     //New card with all initial values
hand.addData(ccard);   
//Many more card are created and inserted

...
// Lots of coding takes place
/*
  Other code
*/

...
UpdateFieldCard(ccard);    //Function to update the values of ccard
emit hand.dataChanged(index(0), index(rowCount()-1));
... 
/*workerThread is pauded using QWaitCondition*/
Run Code Online (Sandbox Code Playgroud)

qml中的ListView仅显示初始数据,即使用addData()插入时的ccard的初始数据.发出dataChanged()信号后,ListView没有得到更新(实际上有时在调试期间列表会更新,但行为是不可预测的).此外QQmlChangeSet错误前,我渐渐消失了.应该beginInsertRows()和之间有一些时差dataChanged()吗?无论我是从主线程还是工作线程调用dataChanged(),它都不会更新.请给出建议.

Ans*_*mar 2

以前,我使用信号和槽机制通过传递引用来添加数据(如论坛中给出的链接中所述)。问题是,数据更改并且发出 dataChanged() 信号后它没有更新。在谷歌上,我发现在信号/槽连接中通过引用传递值不是一个好主意。我将引用我在这里找到的内容

接收槽无论如何都无法修改原始数据(同时被误导认为可以)。此外,Qt 信号/槽背后的一点是信号发射器不知道连接到它的是什么,或者有多少个连接。如果有两个连接的槽,并且它们都尝试修改通过引用传递的对象,那么就有可能出现各种错误。在有限的情况下,它可以与非排队连接一起工作,但它仍然是糟糕的设计。

所以后来我决定通过引用传递,但这也是一个坏主意。使用排队连接时,不能将非常量引用作为信号和槽中的参数传递。

如果希望通过引用传递,则使用 QMutex 来防止多个侦听器修改数据的问题将避免出现问题。然而,这是学术性的,因为在 QMetaObject::activate 中,如果连接类型是 AutoConnection 并且发送者和接收者位于不同的线程中,则该值将被复制。请参阅此处:woboq.com/blog/how-qt-signals-slots-work.html

我的问题的解决方案是数据应该从主线程而不是工作线程更新,为此我使用了 Qt 文档中所述的排队连接(方法对象应该在主线程中声明)并使该方法可调用。这对我有用。但在极少数情况下,我会得到错误的结果,我认为这可能是由于某些运行工作线程的代码造成的。