How to efficiently emit dataChanged signal?
-
Suppose that I have a table view of size 10x10. Suppose that I want to emit dataChanged signals for (1,3), (1,5), (1,7) and (4,3), (4,5), (4,7). Is it faster to emit dataChanged signals individually for each cell (6 times in total) or just emit a single dataChanged signal with topLeft (1,3) and bottomRight (4,7)? Is there a best practice for this case?
-
@VRonin said in How to efficiently emit dataChanged signal?:
The range method will just trigger a total repaint of the view(port)
Interesting. You are saying that
dataChanged(index(0, 0), index (0, 1))
(any range, smallest) is implemented in attachedQTableView
as complete, all-cells/viewport repaint; no attempt is made in code to recognise 2-cell range and treat as 2-cell repaint asdataChanged(index(0, 0), index (0, 0)); dataChanged(index(0, 1), index (0, 1));
would be? Or, indeed, are the multiple separate ones buffered for repaint anyway and if more than a single cell always repaints completely?Not complaining, just would like to know the internal behaviour (preferably without you telling me to look thru the source for myself!).
-
@JonB said in How to efficiently emit dataChanged signal?:
u are saying that dataChanged(index(0, 0), index (0, 1)) (any range, smallest) is implemented in attached QTableView as complete, all-cells/viewport repaint;
Yes, you can see a discussion on the topic here: https://forum.qt.io/topic/89623/ideas-to-optimise-qabstractitemview-datachanged
-
@VRonin
Thanks for that link. I don't have time to read through 24-odd replies! Something basic like "if the cell range is "small" compared to the complete row/columns size do it by individual cell repaint" might (or might not!) be worthwhile. When my changed cell range is 1x2, say, that might improve when the table view is 100x100? :) -
It all depends how many are actually within the viewport and how expensive is to calculate where they are. That's why we got stuck, there is no good answer unless you know with high confidence what is being displayed.
The quick answer is: if the number of cells changed is > the number of cells "normally" visible then just use a range and repaint it all.
If you don't the view would have to calculate the rect of each item changed and that is almost as expensive as painting it so even if they are off screen it will be costly. -
@VRonin said in How to efficiently emit dataChanged signal?:
The quick answer is: if the number of cells changed is > the number of cells "normally" visible then just use a range and repaint it all.
That sounds fine. But earlier you said
The range method will just trigger a total repaint of the view(port) (unless you are using a custom view)
First way look at number of cells changed to decide whether individually or whole repaint, second way always claims to do whole repaint regardless of how many cells in range/total.
-
I did a little tweaking for Qt6: https://codereview.qt-project.org/c/qt/qtbase/+/285280
-
@Christian-Ehrlicher Oh, brutal... I'm not sure it's a straight improvement when
topLeft!=bottomRight
. This calculatesvisualRect
for the entire range + painting those in the viewport. It's not a cheap operation. It might well be that repainting the entire viewport might be cheaper. Am I missing something here?Edit:
I even commented on the code review. Man my memory is toying with me -
@VRonin said in How to efficiently emit dataChanged signal?:
It might well be that repainting the entire viewport might be cheaper. Am I missing something here?
As always - it depends.
The problem is that you can't simply use the first topLeft and last bottomRight coordinates since they might be reordered. But it should be enough to calculate only the ones marked with 'x' here:x x x x
x 0 0 0
x 0 0 0even if they are reordered we can be sure to get topLeft and bottomRight coordinates - or am I wrong?
x 0 0 0
x x x x
x 0 0 00 0 x 0
x x x x
0 0 x 0and QAIV::dataChanged() is virtual so everyone can add it's own logic depending on the use case if it's really a bottleneck.
-
@Christian-Ehrlicher said in How to efficiently emit dataChanged signal?:
or am I wrong?
If the first row/column is hidden you are f***ed.
I think what you did is totally correct. I'm just not convinced is that much of a step up vs the previous -
@VRonin It simply depends on the usecase - if they're not visible and there are not much cells in the range than mine is faster.