QComboBox 省略了所选项目上的文本
QComboBox elided text on selected item
所以,我有一个 QComboBox。
如果 currentText() 对于小部件来说太长,那么我想显示一个省略号。
像这样:
所以 :
void MyComboBox::paintEvent(QPaintEvent * )
{
QStylePainter painter(this);
QStyleOptionComboBox opt;
initStyleOption(&opt);
painter.drawComplexControl(QStyle::CC_ComboBox, opt);
QRect rect = this->rect();
//this is not ideal
rect.setLeft(rect.left() + 7);
rect.setRight(rect.width() - 15);
//
QTextOption option;
option.setAlignment(Qt::AlignVCenter);
QFontMetrics fontMetric(painter.font());
const QString elidedText = QAbstractItemDelegate::elidedText(fontMetric, rect.width(), Qt::ElideRight, this->currentText());
painter.drawText( rect, elidedText, option);
}
这是完美的工作。
问题是注释之间的代码,因为我对左右边界的距离进行了硬编码。这让我感到畏缩。
没有该代码的结果是:
有没有人知道更通用的方法,无需硬编码?
谢谢
文本的绘制位置完全取决于使用的样式。您可以使用 QStyle::subControlRect
获取有关(某些)子元素定位的信息。与组合框文本最匹配的子控件似乎是 QStyle::SC_ComboBoxEditField
,但如果该项目有图标,则也需要考虑这一点。如果项目没有图标,您可以使用
QRect textRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
QFontMetrics fontMetric(painter.font());
const QString elidedText = QAbstractItemDelegate::elidedText(fontMetric, textRect.width(), Qt::ElideRight, this->currentText());
opt.currentText = elidedText;
painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
您可能想看看例如QFusionStyle::drawControl
工作细节。
一般来说,如果您希望所有组合框都省略文本,您应该考虑实现自己的 QProxyStyle
并且只为 QStyle::CE_ComboBoxLabel
覆盖 MyStyle::drawControl
。
这是我一直在使用的解决方案:
void CustomComboBox::paintEvent(QPaintEvent * /*event*/)
{
QStyleOptionComboBox opt;
initStyleOption(&opt);
QStylePainter p(this);
p.drawComplexControl(QStyle::CC_ComboBox, opt);
QRect textRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
opt.currentText = p.fontMetrics().elidedText(opt.currentText, Qt::ElideRight, textRect.width());
p.drawControl(QStyle::CE_ComboBoxLabel, opt);
}
这种方法与您的示例代码和 E4z9 建议的片段的组合非常相似。我只是想我会为将来来到这里的其他人提供整个方法。
所以,我有一个 QComboBox。
如果 currentText() 对于小部件来说太长,那么我想显示一个省略号。
像这样:
所以 :
void MyComboBox::paintEvent(QPaintEvent * )
{
QStylePainter painter(this);
QStyleOptionComboBox opt;
initStyleOption(&opt);
painter.drawComplexControl(QStyle::CC_ComboBox, opt);
QRect rect = this->rect();
//this is not ideal
rect.setLeft(rect.left() + 7);
rect.setRight(rect.width() - 15);
//
QTextOption option;
option.setAlignment(Qt::AlignVCenter);
QFontMetrics fontMetric(painter.font());
const QString elidedText = QAbstractItemDelegate::elidedText(fontMetric, rect.width(), Qt::ElideRight, this->currentText());
painter.drawText( rect, elidedText, option);
}
这是完美的工作。 问题是注释之间的代码,因为我对左右边界的距离进行了硬编码。这让我感到畏缩。
没有该代码的结果是:
有没有人知道更通用的方法,无需硬编码? 谢谢
文本的绘制位置完全取决于使用的样式。您可以使用 QStyle::subControlRect
获取有关(某些)子元素定位的信息。与组合框文本最匹配的子控件似乎是 QStyle::SC_ComboBoxEditField
,但如果该项目有图标,则也需要考虑这一点。如果项目没有图标,您可以使用
QRect textRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
QFontMetrics fontMetric(painter.font());
const QString elidedText = QAbstractItemDelegate::elidedText(fontMetric, textRect.width(), Qt::ElideRight, this->currentText());
opt.currentText = elidedText;
painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
您可能想看看例如QFusionStyle::drawControl
工作细节。
一般来说,如果您希望所有组合框都省略文本,您应该考虑实现自己的 QProxyStyle
并且只为 QStyle::CE_ComboBoxLabel
覆盖 MyStyle::drawControl
。
这是我一直在使用的解决方案:
void CustomComboBox::paintEvent(QPaintEvent * /*event*/)
{
QStyleOptionComboBox opt;
initStyleOption(&opt);
QStylePainter p(this);
p.drawComplexControl(QStyle::CC_ComboBox, opt);
QRect textRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
opt.currentText = p.fontMetrics().elidedText(opt.currentText, Qt::ElideRight, textRect.width());
p.drawControl(QStyle::CE_ComboBoxLabel, opt);
}
这种方法与您的示例代码和 E4z9 建议的片段的组合非常相似。我只是想我会为将来来到这里的其他人提供整个方法。