How can I make my listview that uses custom widgets more efficient?
-
Hi!
Here is a picture of my QListView:
Essentially, I have a
QSortFilterProxyModel
and in thedata
function I callQListView::setIndexWidget
in order to insert my custom widget into the item.If you're curious about what this looks like, here is the code inside the
data
function to set the widget:if ( !m_view->indexWidget(index) ) { QWidget *widget = new NoteListItemWidget(item->note()); m_view->setIndexWidget( index, widget ); item->setWidget(widget); if ( m_view->currentIndex() == index ) item->setSelectedStyle(true); }
How it works: I first check if the current QModelIndex has an existing indexWidget. If not, I create a new instance of my custom widget and set it as the index widget. The extra code there tweaks the styling if it is a selected item.
Question
So, I am wondering how I could make this more efficient. This will work fine for many users of my app, but for those who have over 1,000 notes it can add some delay when the user clicks the "All Notes" button which would create ~1,000 instances of my custom widget.
The Qt docs basically state that I should not be using
setIndexWidget
: "This function should only be used to display static content within the visible area corresponding to an item of data. If you want to display custom dynamic content or implement a custom editor widget, subclass QItemDelegate instead."I've looked into QItemDelegate and it seems like it would be pretty complex to re-make my custom widget by painting it all from scratch.
What do you think I should do? I was also thinking that it might be faster to take my logic code above and offload it to a thread. This would likely solve the lag problem when trying to view 1,000+ notes.
EDIT: If you'd like to see the source code, all of it is on Gitlab. Here's the QSortFilterProxyModel.
-
Hi
You could try
https://pastebin.com/XrppLZ3m
It would basically use an image for your custom widget and should speed up creation of many notes.
Its a compromise between setIndexWidget and a full Delegate. So when not in edit mode, an image is drawn
which should be faster overall. However, i never got around to speed test it so no promises :) -
@DougBeney
well you would have to adjust the code slightly to allow it to handle that since the image would
be different.However, i do wonder if your custom widget is just some fonts & text and a star
in that case paint it from a delegate should be not that demanding ? -
You're right!
I ended up successfully moving to a delegate!
Works beautifully. Painting in Qt was way less scary than I thought it would be.
Before this I actually got my threaded idea working. It got the job done, but was not the best solution. This is so much better.
Thanks for the help.
In case anyone runs into this post in the future, here is my custom delegate.
I also had to create a custom ListView in order to get the correct click behavior I wanted. (When you click the star, it shouldn't select the listview item)