问题
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
回答1:
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
.
回答2:
This is the solution I've been using:
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);
}
This approach is very similar to a combination of your sample code and the snippet E4z9 suggested. I just thought I'd include the whole method for others coming here in the future.
来源:https://stackoverflow.com/questions/41360618/qcombobox-elided-text-on-selected-item