I am using a custom QStyledItemDelegate
in order to display data in a QTreeWidget
. Thus I have implemented the paint()
and the sizeHint()
functions.
The painting works fine, but I have some issues with the sizeHint
. The problem is that I am displaying some text that will wrap if the horizontal space is insufficient for displaying without wrapping. The issue is that Qt does not seem to call the sizeHint
function when the QTreeWidget
is being resized. Only the paint
function gets called in these cases but as my items change their row height (depending on if and how often they wrap lines) this causes the layout of the tree to get messed up.
The situation currently is: The layout works as expected right after the widget's creation and as long as it does not get resized, everything works like charm. If however one is to resize the widget, the text starts or stops wrapping,changing the item's height (this is all done in the paint
function that still gets called regularly) and then the vertical layout of the tree is destroyed (either the items are spaced out with huge distances or they start overlapping, depending on whether the items are now taking less or more vertical space to render).
I have tried explicitly setting uniformHeights
to false
and wordWrap
to true
on the tree widget, but this did not seem to have any effect.
This is an exemplary sizeHint
function:
QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem &inOption, const QModelIndex &index) {
QStyleOptionView option = inOption;
initStyleOption(option);
QTextDocumentOptioon opt;
opt.setWrapMode(Qt::WrapAtWordBoundaryOrAnywhere);
opt.setAlignment(Qt::AlignLeft)
QTextDocument doc;
doc.setDefaultTextOption(opt);
doc.setTextWidth(option.widget->size().width());
doc.setHtml("An example text that may or may not wrap");
return doc.size();
}
How do I get the tree widget to call the item delegate's sizeHint
function to be called more frequently (on all resize events)?
This answer is partly inspired by the comments from scopchanov - thanks for that!
In order to get the tree widget to update its layout, I had to first of all subclass QTreeWidget
and then override QTreeWidget::resizeEvent
. This way I get a hook into which I can inject code every time the widget is being resized.
In order to get the widget to actually update its layout, I use QAbstractItemView::scheduleDelayedItemsLayout
(QAbstracTItemView::executeDelayedItemsLayout
should work as well).
Thus all in all my resizeEvent
function looks like this:
void MyCustomTree::resizeEvent(QResizeEvent *event) {
scheduleDelayedItemsLayout();
QTreeWidget::resizeEvent(event);
}
Refs: