QListView flicker when inserting items in IconMode
-
I put together a repro project that shows QListView Flickering when frequently inserting items (100/sec) in IconMode. The flicker goes away if I insert 10 items /sec. When looking at the repro vide frame-by-frame, I see that the view goes all blank for a frame. My item model is using QAbstractItemModel. This does not repro if the ListView is not in Icon Mode.
This happens on MacOS and Ubuntu. have not tried Windows.
The repro is in https://github.com/OzerOzdemir/BugReports and the video showing the flicker is in the same project (sorry, it is in .mov format).
I tried to keep the project as simple as possible, but used a thread to emit item creation (to keep close to my scenario).
There is not really much to the code. I have removed the thread synchronization from the Catalog class since it is not relevant to this repro. Below is part of the model.
BTW, On a side-note, I am using QT 6.0.1, but Creator System Info says 5.15.2. I believe it mentions what Creator is built on? I'd expect it report what SDK I have instead.
QVariant ItemModel::data(const QModelIndex &index, int role) const { if (index.row() >= rc) { return QVariant(); } Item a = catalog->getItem(index.row()); switch (role) { case Qt::DisplayRole: { return a.Name; } case Qt::DecorationRole: { return a.thumbnail; } case Qt::SizeHintRole: { return cellSize; } } return QVariant(); } bool ItemModel::insertRows(int row, int count, const QModelIndex &parent) { if (parent.isValid()) return false; beginInsertRows(parent, row, row + count -1); rc+= count; endInsertRows(); return true; } void ItemModel::addItem(Item astroFile, int row) { insertRow(row); }
Here are three frames that show the flicker:
(
-
To close on this, I have verified that if I change the model to have a local copy of the items, i.e. instead of doing
Item a = catalog->getItem(index.row());
which fetches the item from a different thread, then there is no flicker in the List View. I still believe it is a valid bug, but at least I know under what conditions it happens, so I can work around it. -
@ZeroOne said in QListView flicker when inserting items in IconMode:
I'd expect it report what SDK I have instead.
Why? It's the about dialog box of the QtCreator application...
For your problem: don't insert the 100 items one by one but in bulk. 100Hz is not visible to anyone and just creates heavy cpu usage for nothing.
-
I also thought that it had to do with refresh rate, but I believe this is a real bug, the frequent insertion only makes it more visible. Even if I enter one item per second, I eventually see the flicker, I just have to wait a longer time for it to happen in this test app. Note that this does not repro for ListMode, only for IconMode (for me at least).
If it would be once in a while, I wouldn't bother, but keep in mind that this is a cut-down minimal test application. On my product app with all UI elements, the flicker is unbearable. Especially when I resize the window, when the items update, when I remove items. Notice that slider at the bottom, it is to change the size of the items. I have removed that functionality in the repro project (github link in the original post), but when I enable all other features I use in my app, the flickers happen even if I don't add an item and that makes it just unusable.
-
Your code has threading issues - getItem() is not thread safe. Please add a mutex. Don't think it's the problem though.
-
Hi,
Does it really make sense to set the resize mode to adjust with so many items ?
-
@SGaist said in QListView flicker when inserting items in IconMode:
Does it really make sense to set the resize mode to adjust with so many items ?
This is only to make the issue repro easier. The flicker happens in different scenarios as well, but I just tried to put together a repro case that is small in code and easy to reproduce.
@JoeCFD said in QListView flicker when inserting items in IconMode:
@ZeroOne save your data in a queue and add them one after another at slower rate which does not trigger any flickering.
Even if I add one item per second, the flickering happens. In fact it happens even if I don't add any more items at all. I have added a second video to the git repo that has larger icons (set the QSize to 200 instead of 20). Run it and wait until all have been inserted, ignore the flickers at that time. Then once all have been inserted, just maximize the window, and you'll see it flickers. Maybe I should have gone with that scenario as my bug report.
The flickering is happening because QListView is drawing a blank frame. That is almost always a bug in the painting of the ui element. I am not saying that I am using tiny images in my product. My point by providing this repro case was that it is easy to repro, happens on multiple platforms and is easy to visually detect. If the devs can identify this issue, it might help with the flickering of other scenarios as well since it may be the same root cause.
-
@JoeCFD said in QListView flicker when inserting items in IconMode:
@ZeroOne Check the parent setting in your widgets. I had a similar issue in a widget for full screen mode(nullptr as parent) which was solved by assigning a parent to it.
Thanks for the heads-up. I believe I have some bugs related to that in my product. I'll take a closer look to make sure I fix those. I don't think that is the reason for this repro though.
I started putting together an even simpler repro case, with no external thread, and the flicker does not repro!...
I have the feeling that it is related to the
getItem()
line below. If I use a private List, instead of requesting it from the catalog, it does not flicker. Spending too much time here maybe?Will continue to investigate.
QVariant ItemModel::data(const QModelIndex &index, int role) const { if (index.row() >= rc) { return QVariant(); } Item a = catalog->getItem(index.row()); // <==== This switch (role) { case Qt::DisplayRole: { return a.Name; } case Qt::DecorationRole: { return a.thumbnail; } case Qt::SizeHintRole: { return cellSize; } } return QVariant(); }
-
To close on this, I have verified that if I change the model to have a local copy of the items, i.e. instead of doing
Item a = catalog->getItem(index.row());
which fetches the item from a different thread, then there is no flicker in the List View. I still believe it is a valid bug, but at least I know under what conditions it happens, so I can work around it.