PDA

View Full Version : Updating of view instead of full model's data repainting



Toniy
21st January 2016, 08:09
Hello everyone.

I have a model subclassed from QAbstractItemModel and QTableView (or another derivant of QAbstractItemView). Model catches lots of data that arrives very frequently (e.g. one data entry for every 10ms).

So the questions are:

1. Does view repaint all model's entries from scratch on every model update by default?
2. If answer of first question is "yes", is there any proper way to update shown data or paint only visible data instead of full repainting?

My first thoughts of it were making some delay in model and implementing delegate. Delay of repainting was useless because even one iteration of full repainting lasts for critical time when there is a lot of data accumulated (i.e. time of full repainting becomes longer than time elapsed between two updatings of model).

So I thought about delegate. Thus next bunch of questions is:

3. Is there any proper way to check visibility of obtained data with delegate? (I figured out that proper implementation of delegate defines methods of repainting and intercommunications of model and view but not certain data selection, am I right about it?)

4. If all of my thougts are completely wrong does solution of that issue exists at all?

Thanks in advance.

P.S. Are specified tags for this thread correct and sufficient?

==========

Update: at the moment I found this example of handling big data sets with ModelViews: http://doc.qt.io/qt-5/qtwidgets-itemviews-fetchmore-example.html

d_stranz
21st January 2016, 18:05
1. Does view repaint all model's entries from scratch on every model update by default?

If the entire model is updated, the view repaints only the part that is able to fit onscreen. I do not know if the standard QTableView is smart enough to only update the affected rows if only part of the model changes.


Model catches lots of data that arrives very frequently (e.g. one data entry for every 10ms).


This is the real source of your performance problem if your model is issuing a change call for every new data entry. What methods do you call when each new piece of data arrives?


2. If answer of first question is "yes", is there any proper way to update shown data or paint only visible data instead of full repainting?

The first answer is no, but if it was yes, you would have to write your own QTableView implementation to do that.


My first thoughts of it were making some delay in model and implementing delegate. Delay of repainting was useless because even one iteration of full repainting lasts for critical time when there is a lot of data accumulated (i.e. time of full repainting becomes longer than time elapsed between two updatings of model).


If your model is emitting signals indicating a change with every small modification, then your view will update on every one of them. Of course this will be slow for a large model or table view.


3. Is there any proper way to check visibility of obtained data with delegate? (I figured out that proper implementation of delegate defines methods of repainting and intercommunications of model and view but not certain data selection, am I right about it?)

A delegate's paint() method will be called only for items that -are- visible. Qt is smart enough that it doesn't issue paint events for things that aren't visible.


I found this example of handling big data sets

I think you would still need to change the way your model is notifying about new data arriving.

ChrisW67
21st January 2016, 21:33
A view is for the user to see. The user cannot possibly see and make use of 100 textual updates per second so it makes little sense to even try displaying them as they arrive.

If you are, as I suspect, adding 100 new records per second then I suggest you change the model:
Start a 500 millisecond timer.
Accumulate new records in a data structure outside the data structure exposed through the model.
When the timer expires, add all buffered records to the model in one movement and restart the timer.
Only at this point will the view change, and only if the new records are visible.
The timer handles when the data flow stops and ensures the last partial buffer is added.

Toniy
22nd January 2016, 08:47
Got it!
Well, the point is that I store all data inside model and when new data for storing arrves I use setData() method which emits dataChanged() signal.
According to your replies emitting of this signal very often reduces performance, doesn't it?
Thus do I understand correct that model in Qt Model/View is not recommended for direct data storing but only for accessing to update views (i.e. model is a wrapper around existed storing structure but not storing structure itself)?
If so, is it correct that usage of virtual methods of QAbstractItemModel only is not sufficient for custom models (i.e. at least I need to bind the model to specific data structure)?

anda_skoa
22nd January 2016, 11:53
The model is intended to be the interface to the data, but it can also contain the data if there is no other place where it would be stored.

That is, however, irrelevant for what ChrisW67 suggested. Even if you store the data inside the model instance, you can still update in batches.

The update method, independent of whether the model stores data or access data stored elsewhere, would call QAbstractItemModel::beginInsertRows(), either add the data batch or update the lookup information and then call QAbstractItemModel::endInsertRows().

Cheers,
_

d_stranz
22nd January 2016, 16:14
(i.e. model is a wrapper around existed storing structure but not storing structure itself)?

It is my personal preference to use models in the form of wrappers. In the scientific data analysis code that I write, I like to create all of the data structure and processing code in pure C++, as independently of Qt as possible. For display purposes, I then wrap a class based on QAbstractItemModel or QAbstractTableModel around these data structures and use filters and proxies to select out the parts of the larger model I want to appear on screen.

Should some better GUI development tool come along in the future (something I can't imagine), then the impact on my core code can be minimized.