Manually refresh QListWidget while inserting
-
I'm currently adding a huge list of items in my QListWidget, the process takes approximately from 5 to 10 secs.
I would like to manually refresh the new items in the widget to show the "progress", how can I efficiently do it? Apparently, calling
repaint()
andudpate
refreshes all the items, so it takes more time as there is more items, and the widget refreshes itself when it comes back to the event loop.While I'm adding the items to the list, I'm using a recursive call, so I won't return to the event loop before the end.
If possible, I would like to add an item and refresh the last item to be shown, and so on (or maybe each 5 items, for instance).
Thank you
-
@VRonin Thank you for the hint. It works almost as expected. The scrollbar shrinks but the widget stays empty. But when I focus on another app or refocus on mine, the content on the widget flashes and disappears again.
Is it related to the speed of insertion? Is there a last thing missing?
-
Hi,
How many items are you trying to add ?
In any case, it looks like you should rather consider QListView with a custom QAbstractListModel.
Doing so you will be able to implement smarter algorithm to handle injection of big amount of data like batch insertion maybe a bit of thread to offload the work from the main thread etc.
Hope it helps
-
@SGaist Thanks for the suggestion. Currently, I'm adding as much directories and files in a selected folder on the computer. So it can be from 1 to ... elements.
Before subclassing all that, I made another class which receives the
QListWidget
and has acrawl
method. When crawling, I tried to call:QtConcurrent::run(crawler, &Crawler::crawl)
, which works correctly but still freezes the GUI. Is that what you suggested?EDIT: BTW, I'm adding them by creating
QListWidgetItem
s 1 by 1. -
I was using
QFuture<T>::waitForFinished()
which was blocking the main thread. I now send a signal when it's finished and return peacefully to the main loop.I'm still unable to see the changes in the list, live. Doing a refresh (using
refresh
orQApplication::processEvents()
) will refresh all the list, is it possible to only "commit" the last added element? -
Why not use a QFileSystemModel ?
-
@SGaist Because I think it would be more expensive to use this model then parse it searching for what I have to hide. So I thought, it would be faster to just recursively parse the filesystem myself and immediately sort what I need to keep or hide. Isn't it?
-
You can add custom QSortFilterProxyModel that will remove what you don't want.
-
@SGaist Actually, "sorting" here means I have to exclude considering characteristics, like filename length. For real, is it heavier to feed the widget myself, than using the Model, View and sorter?
If you say so, as a forgotten Qt Ambassador I can only trust a permanent Qt Champion ;)
But I still would like to know what's the problem with my code. Anyway, I will look for the issue later
-
It's rather the filter part that is interesting in that class for your use case.
Not knowing your code I can't comment ;)
-
Finally... After few docs and experiences, I don't know how but I missed the fact that
QWidget
s are not reentrant (thanks to @kshegunov), and I also missed the fact that signals and slots are made for that.@SGaist So, thanks for your advices but doing real MVC made my app too complicated for what it does. In a more constructed project, I would do what you suggested. I've simplified mine:
- Choose your "root" directory
- The
Crawler
crawls (recursively inQt::Concurrent
) and send a signal when theQFileInfo::fileName().length()
is more than x characters - A slot in the
MainWidget
adds the item in theQListWIdget
That's all for now (auto-rename for later), so few lines of code. Thank you for your advices.