ListView中没有更新 [英] No update in ListView

查看:112
本文介绍了ListView中没有更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个从 QAbstractListModel 派生的类,并重新实现了所有必需的功能.我创建了一个对象,将一些初始数据填充到模型中(所有beginInsertRows等都完成了),然后通过 setContextProperty 将其(对象)传递给qml.我正在使用 QQuickView .通过 show()命令显示qml后,将生成一个 QThread ,其中将使用Model对象的指针.该线程通过直接调用 Model 的 addData(..) 函数(具有 beginInsertRows 等)不断向模型添加数据.

I made a class derived from QAbstractListModel and re-implemented all the necessary functions. I create an object of it, fill in some initial data into the model (all beginInsertRows etc done) and then pass it (the object) to qml via setContextProperty. I'm using QQuickView. Once qml is shown by show() command, I spawn a QThread in which I use the pointer of the Model object. The thread keeps adding data to the model via direct call to Model's addData(..) function (which has beginInsertRows etc).

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

Problem: There is no update of the UI. I get the following listed in the Application Output pane in QtCreator:

QObject::connect: Cannot queue arguments of type 'QQmlChangeSet'
(Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().)

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

The form here shows the exactly same problem but I can't use signal and slot as mentioned there.

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

Running addData() from main thread (using signal-slot as mentioned in the link but not subclassing QThread) did update the ListView to the initial data but the view is not updated after dataChanged() signal. Let me explain it little bit more clearly.

/*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*/

qml中的

ListView仅显示初始数据,即使用addData()插入ccard时的初始数据.发出dataChanged()信号后,ListView不会得到更新(实际上有时在调试过程中,列表会被更新,但是行为是不可预测的).我早些时候遇到的 QQmlChangeSet 错误也消失了. beginInsertRows() dataChanged()之间应该有一些时间差吗?无论是从主线程还是辅助线程调用dataChanged(),它都不会更新.请提出建议.

ListView in qml is showing only the initial data, i.e, initial data of ccard when it was inserted using addData(). ListView is not getting updated after emitting dataChanged() signal (actually sometimes during debugging the list get updated but the behaviour is unpredictable). Also QQmlChangeSet error I was getting earlier is gone. Should there be some time difference between beginInsertRows() and dataChanged()? Whether I call dataChanged() from main thread or worker thread, it's not updating. Please give suggestions.

推荐答案

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

Previously I was using signal and slot mechanism to add data by passing reference(as told in the forum in the link given in question). Problem with that was, it was not updating after the data was changed and dataChanged() signal was emitted. On google I found that passing values by reference in signal/slot connections is not a good idea. I shall quote what I found here

接收槽无论如何都无法修改原始文件(同时误以为可以这样做).此外,Qt信号/插槽后面的一点是,信号发射器不知道连接到它的是什么,或者不知道有多少个连接.如果有两个相连的插槽,并且它们都试图修改通过引用传递的对象,那么您就有各种潜在的错误发生.在非排队连接的情况下,它可以在有限的情况下工作,但是它仍然是糟糕的设计.

The receiving slot would not be able to modify the original anyway (while being mislead into thinking that it could). Further, the point behind Qt signals/slots is that the signal emitter does not know what is connected to it, or how many connections there are. If there are two connected slots, and they both try to modify the object that was passed by reference then you have all sorts of potential for bugs. It will work, in limited situations, with non-queued connections, but it's still bad design.

因此,我决定通过引用传递,这也是一个坏主意.使用排队连接时,不能在信号和插槽中将非常量引用作为参数传递.>

So then I decided to pass by reference which also turned out to be a bad idea.You can't pass a non-const reference as an argument in signals and slots when using a queued connection.

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

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

The solution to my problem is that the data should be updated from the main thread instead from worker thread and to do so I used Queued connection as stated in Qt doc (the methods object should be declared in main thread) and made the method invokable. This worked for me. But still in rare case I get wrong result which I think might be due to some code running the worker thread.

这篇关于ListView中没有更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆