我有一个带有QTableView
的应用程序和一个派生自QAbstractItemModel
的模型:表的第一列包含一个文本(每行的标签),而第二列显示的值是可以使用从自定义项委托创建的QComboBox
来选择。表的内容可能会动态变化(行数,语言......)。
我想调整列的大小,以便第二个适合内容,第一个延伸占据剩余空间。
我的第一次尝试是:
tblData->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
tblData->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
结果:
问题在于,当选择QComboBox
时,它不适合该部分并且会被裁剪:
我设法通过手动增加宽度来解决此问题:
tblData->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
tblData->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed);
tblData->resizeColumnToContents(1);
tblData->horizontalHeader()->resizeSection(1, tblData->horizontalHeader()->sectionSize(1) + 40);
现在的问题是,通过使用这样的常量(在这种情况下为40),截面的宽度将根据显示的值而不是所有可能的值而变化(如果已经显示最大的那些,如果只有最短的那么)。此外,该常量将取决于使用的样式,因为它还与QComboBox
消耗的空间有关。
我已经考虑使用Qt::SizeHintRole
手动计算剖面宽度,但它完全被忽略了。即使是这样,我也无法计算文本的实际宽度(使用QFontMetrics::width
),因为我在模型中没有任何字体信息。
我尝试过的另一种方法是在QComboBox
方法中设置QItemDelegate::createEditor
的调整大小政策:
QWidget* myItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
auto comboBox = new QComboBox(parent);
comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
// ...
}
但现在组合框被裁剪或缩短。
如何根据完整的内容范围而不仅仅是可见数据来解决设置部分大小?
我用我迄今为止找到的最好的方法,以及我现在在项目中使用的方法,自我回答了这个问题,但我不相信它(详细说明答案的原因)所以我想知道正确的方法。谢谢!
答案 0 :(得分:2)
委托中的sizeHint
是正确的方法,但是,不是创建编辑器,而是填充QStyleOptionComboBox
结构并使用qApp->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, nullptr);
,其中sh
是内部字符串的大小。您可以使用QFontMetrics
来计算或只调用基类QStyledItemDelegate::sizeHint(...)
。
答案 1 :(得分:0)
我到目前为止找到的最佳选择是重新实现QItemDelegate::sizeHint
:我有来自QStyleOptionViewItem
的字体信息以及要包含在{QComboBox
中的元素列表1}}。
QSize myItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
auto hint = QItemDelegate::sizeHint(option, index);
QFontMetrics fm(option.font);
std::unique_ptr<QWidget> editor(createEditor(nullptr, option, index));
auto comboBox = qobject_cast<QComboBox*>(editor.get());
if (comboBox != nullptr) {
int width = 0;
for (int ii = 0; ii < comboBox->count(); ++ii) {
width = std::max(width, fm.width(comboBox->itemText(ii)) + 20);
}
hint.setWidth(std::max(hint.width(), width));
}
return hint;
}
结果:
此解决方案的缺点是:
QComboBox
所需的额外空间的信息,所以它还没有风格独立(与问题的第二种方法一样) PS:使用QComboBox::sizeHint
这里不起作用,因为大小提示是使用QComboBox::sizeAdjustPolicy
计算的,正如问题中所突出显示的那样,并没有正确地将组合框调整到细胞
<强>更新强>
我已根据评论和已接受答案的说明更新了解决方案。以下是完整的代码供将来参考:
QStringList myItemDelegate::getPossibleValuesForIndex(const QModelIndex& index) const
{
// returns list of all possible values for given index (the content of the combo box)
}
QSize myItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
auto hint = QItemDelegate::sizeHint(option, index);
QFontMetrics fm(option.font);
QStyleOptionComboBox comboOption;
comboOption.rect = option.rect;
comboOption.state = option.state | QStyle::State_Enabled;
Q_FOREACH (const auto& value, getPossibleValuesForIndex(index)) {
hint = hint.expandedTo(qApp->style()->sizeFromContents(QStyle::CT_ComboBox,
&comboOption, QSize(fm.width(value), hint.height())));
}
return hint;
}