How to implement QAbstractItemDelegate::sizeHint()
I'm using an item delegate to render items in a list view. The items are a custom type which constitutes some text and zero or more tags. I want to layout the data with the block of text above the tags. The tags will then be laid out in lines, left aligned, overflowing onto subsequent lines as each line is full. Hopefully you get the idea...
Anyway, my paint method to render this works fine, but my sizeHint, doesn't quite work as expected. Since the amount of vertical space needed to show the text and tags for each item is dependent on width available, I'm using the QStyleOptionViewItem::rect member to indicate the width available, and then calculating the necessary height based on this width. This doesn't work however, as the size of the rect doesn't appear to be representative of the space available, I probably have the wrong idea about its intention. For reference, I initially get a width/height that would appear to be the size of the entire list view area, but before the items are shown, sizeHint gets called several more times with very narrow widths (eg. 36px) in the rect parameter and it is the response to those rects that is used to determine the space required by the items. This results in a line worth of height per tag, when there are multiple tags, and most of that space won't be necessary given that the actual width is much larger and can fit the tags on fewer lines.
So I'd be very grateful if anybody could give me a better idea of how to determine the available width when implementing sizeHint, and more generally help me to understand if there are any general guidelines to be aware of when implementing it. I'm also open to suggestion of different approaches to displaying a list of tags.
The width of your item should be fixed by the available space from the view. Then you have something from which you can calculate the height which gives you your size hint.
Thanks for the reply.
Yes, that was my expectation that the I could use the available space in the view to determine the width, I'm just not sure how to find that out. I had thought that QStyleOptionViewItem::rect would have that, but it clearly doesn't.
Do you know how I can determine the available space in the view?
Onc approach that I have tried is to use the parent of the delegate. If I constructed my delegate with the item view as it's parent, I can get the item view object and use it's rect to determine the width. This doesn't feel right though, as I could just as easily construct the delegate with some other object as it's parent, like the window. Is there a standard way to find the view that a delegate is used in?
A further issue I've had, is that when I do use the view to calculate the height, as I expand the size of my window, sizeHint gets called and correctly shrinks the item. However, while the item itself has shrunk, the extra space that had been allocated to it within the view is left empty, subsequent items are not shifted up to fill up the space. Is there a property of the item view that controls this behaviour?
Any thoughts would be really appreciated.
Ok, it feels a bit silly to post on top of myself again. But, what I've done is make the constructor for the delegate take a QAbstractItemView* to indicate that the itemview it is associated with should be it's parent. I'm then using the parent's rect to determine the available width. I've also set the ListView::resizeMode property to Adjust, so that it lays out the items again.
One last thing I've noted, at least with Qt 4.8.1 on Mac, it appears as though if I only horizontally resize my window (with carefully mouse skils) the amount of vertical space allocated to the items isn't adjusted, even though the sizeHint indicates the item needs more space. It's only when a vertical change to the window occurs that it appears to consider adjusting the vertical space allocated to the items. Does this sound like a bug, or just normal behaviour?
Running into the same issue, but I think maybe it's only a theoretical problem. I'm looking at QItemDelegate source code, at first I didn't really understand why this works. It appears to just set it's size based on what it has and doesn't consider how much size it will actually get.
I guess the key is that it's a 'sizeHint'. So just give the amount of space you'd like in an ideal world and then you'll get a different amount of space to actually paint into. I'll proceed under this assumption and see what happens. :)
bq. One last thing I’ve noted, at least with Qt 4.8.1 on Mac, it appears as though if I only horizontally resize my window (with carefully mouse skils) the amount of vertical space allocated to the items isn’t adjusted, even though the sizeHint indicates the item needs more space. It’s only when a vertical change to the window occurs that it appears to consider adjusting the vertical space allocated to the items. Does this sound like a bug, or just normal behaviour?
Ran into this just now. Solution:
(Even if you're doing all your own drawing, this makes it check the sizeHint whenever the QListView is resized.)
Hope that's helpful to someone, even if it's too late to help you.