I have an application with a QTableView
and a model derived from QAbstractItemModel
: the first column of the table contains a text (a label for each row), while the second column shows a value that can be selected using a QComboBox
created from a custom item delegate. The content of the table may change dynamically (number of rows, language...).
I'd like to resize columns so the second one fits the content and the first one stretches occupying the remaining space.
My first attempt was:
tblData->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
tblData->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
Result:
The problem is that when the QComboBox
is selected it doesn't fit the section and it is clipped:
I've managed to solve this issue by manually increasing the width:
tblData->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
tblData->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed);
tblData->resizeColumnToContents(1);
tblData->horizontalHeader()->resizeSection(1, tblData->horizontalHeader()->sectionSize(1) + 40);
Now the issue here is that by using such constant (40 in this case) the width of the section will vary depending on values displayed rather than in all the possible values (if the largest ones are already displayed vs if only the shortest). Also, that constant will be dependant to the style used, since it is also related to the space consumed by the QComboBox
.
I've thought about using the Qt::SizeHintRole
to manually compute the section width, but it is completely ignored. Even if it was, I cannot compute the actual width of the text (using QFontMetrics::width
) because I don't have any font information in the model.
Another approach I've tried is to set the adjust size policy of the QComboBox
in the QItemDelegate::createEditor
method:
QWidget* myItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
auto comboBox = new QComboBox(parent);
comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
// ...
}
But now the combo boxes are either clipped or shortened.
How can I solve set the section size based on the complete range of content instead of just visible data?
I'm self-answering the question with the best approach I've found so far, and the one I'm using in the project right now, but I'm not convinced with it (I detail reasons on the answer) so I'd like to know the correct way to do it. Thanks!
The sizeHint
in the delegate is the right way to go but, instead of creating an editor, fill a QStyleOptionComboBox
struct and use qApp->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, nullptr);
, where sh
is the size of the internal string. You can use QFontMetrics
to calculate that or just call the base class QStyledItemDelegate::sizeHint(...)
.