Is it possible to add an icon (programmatically, via QtCreator, with or without a stylesheet) to the QGroupBox title?
I want to place a mark close to the title of some of the QGroupBoxes in my GUI. The best place would be to the right of the title, but any other reasonable position (to the left of the title, or in the top right corner of the widget) could be also valid.
The only way I could think of is creating a QLabel with an icon and visually placing it on top of the QGroupBox, in the desired position. But I find this an ugly solution.
Edit
I know there is a way of setting the indicator
used for checkable QGroupBoxes, as any image, both for checked and unchecked states, using stylesheets. But then the QGroupBox must be checkable, etc. I want to add this mark (a small image) independently to the checkability of the QGroupBox.
Unfortunatelly, QGroupBox
does not have a setIcon
method, as QPushButton
does.
A possible solution could be to make QGroupBox
checkable using QGroupBox::setCheckable
and set a custom image as an indicator using a stylesheet like this:
QGroupBox::indicator:unchecked {
image: url(:/images/checkbox_unchecked.png);
}
However, this will make the whole group box disabled, when the checkbox is unchecked.
Having this background in mind, I would suggest you a fairly complex, but also a pretty flexible solution, consisting of the following steps:
Subclass QStyleOptionGroupBox
and declare additional variables as public class attributes:
QPixmap pixmap;
int offset;
int leftSpace;
int rightSpace;
These will be used for passing the decoration pixmap, as well as the placement settings, to the style.
Subclass QCommonStyle
and reimplement QCommonStyle::drawComplexControl
like this:
if (const StyleOptionDecoratedGroupBox *groupBox = qstyleoption_cast<const StyleOptionDecoratedGroupBox *>(opt)) {
QRect textRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
int decorationOffset = 0;
int pixmapRectWidth = 0;
int pixmapHeight = 0;
int textOffset = 0;
if (!groupBox->pixmap.isNull()) {
decorationOffset = groupBox->offset;
pixmapRectWidth = groupBox->leftSpace
+ groupBox->pixmap.width()
+ groupBox->rightSpace;
pixmapHeight = groupBox->pixmap.height();
textOffset = decorationOffset + pixmapRectWidth;
}
textRect.adjust(textOffset, 0, textOffset, 0);
// Draw frame
if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
QStyleOptionFrame frame;
frame.QStyleOption::operator=(*groupBox);
frame.features = groupBox->features;
frame.lineWidth = groupBox->lineWidth;
frame.midLineWidth = groupBox->midLineWidth;
frame.rect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
p->save();
QRegion region(groupBox->rect);
if (!groupBox->text.isEmpty()) {
bool ltr = groupBox->direction == Qt::LeftToRight;
QRect finalRect;
if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) {
finalRect = checkBoxRect.united(textRect);
finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0);
} else {
finalRect = textRect;
}
region -= finalRect;
}
p->setClipRegion(region);
proxy()->drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
p->restore();
}
// Draw icon
if (!groupBox->pixmap.isNull()) {
p->fillRect(decorationOffset, 0, pixmapRectWidth, pixmapHeight, opt->palette.window().color());
proxy()->drawItemPixmap(p, QRect(decorationOffset, 0, pixmapRectWidth, pixmapHeight),
Qt::AlignCenter, groupBox->pixmap);
}
// Draw title
if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
QColor textColor = groupBox->textColor;
if (textColor.isValid())
p->setPen(textColor);
int alignment = int(groupBox->textAlignment);
if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
proxy()->drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
if (groupBox->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*groupBox);
fropt.rect = textRect;
proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
} else {
QCommonStyle::drawComplexControl(cc, opt, p, widget);
}
Subclass QGroupBox
and reimplement QGroupBox::paintEvent
like this:
CustomStyle style;
QPainter painter(this);
StyleOptionDecoratedGroupBox option;
initStyleOption(&option);
option.pixmap = m_pixmap;
option.offset = m_offset;
option.leftSpace = m_leftSpace;
option.rightSpace = m_rightSpace;
style.drawComplexControl(QStyle::CC_GroupBox, &option, &painter, this);
Note: This solution does not work well when the group box is checkable.
The solution requires a lot of work, but fortunatelly I have created the necessary classes for you, as well as a complete example of how to use them in your own projects. The code is available on GitHub.
The provided example produces the following result:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With