So, I have a QComboBox.
If the currentText() is too long for the widget then I want to show an ellipsis.
Like this :
So :
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);
}
This is working flawlessy. The problem is the code in between the comments, because I am hardcoding the distances from the left and right border. It makes me cringe.
The result without that code is:
Does anybody know a more general way to do this, without hardcoding? Thank you
Where the text should be drawn exactly depends on the used style. You can get information about (some of) the positioning of subelements with QStyle::subControlRect
. The subcontrol that matches the combo box text best seems to be QStyle::SC_ComboBoxEditField
, though if the item has an icon, this needs to be taken into account as well. If the items do not have icons, you can go with
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);
You might want to have a look at how e.g. QFusionStyle::drawControl
works for details.
In general, if you want all your combo boxes to elide the text, you should consider implementing your own QProxyStyle
and only override MyStyle::drawControl
for QStyle::CE_ComboBoxLabel
.