c++ - 如何将图标添加到 QGroupBox 标题?
问题描述
是否可以向 QGroupBox 标题添加图标(以编程方式,通过 QtCreator,有或没有样式表)?
我想在我的 GUI 中一些 QGroupBoxes 的标题附近放置一个标记。最好的位置是在标题的右侧,但任何其他合理的位置(在标题的左侧,或在小部件的右上角)也可能是有效的。
我能想到的唯一方法是创建一个带有图标的 QLabel 并将其直观地放置在 QGroupBox 顶部的所需位置。但我发现这是一个丑陋的解决方案。
编辑
我知道有一种方法可以使用样式表将indicator
用于可检查的QGroupBoxes设置为任何图像,无论是选中状态还是未选中状态。但是 QGroupBox 必须是可检查的,等等。我想将此标记(一个小图像)独立添加到QGroupBox的可检查性中。
解决方案
背景
不幸的是,QGroupBox
没有setIcon
方法,因为QPushButton
没有。
一种可能的解决方案是使用如下样式表QGroupBox
进行检查QGroupBox::setCheckable
并设置自定义图像作为指示器:
QGroupBox::indicator:unchecked {
image: url(:/images/checkbox_unchecked.png);
}
但是,当未选中复选框时,这将禁用整个组框。
解决方案
考虑到这一背景,我建议您使用一个相当复杂但也非常灵活的解决方案,包括以下步骤:
子类化
QStyleOptionGroupBox
并将附加变量声明为公共类属性:QPixmap pixmap; int offset; int leftSpace; int rightSpace;
这些将用于将装饰像素图以及放置设置传递给样式。
像这样子类化
QCommonStyle
和重新实现QCommonStyle::drawComplexControl
: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); }
像这样子类化
QGroupBox
和重新实现QGroupBox::paintEvent
: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);
注意:当分组框可以选中时,此解决方案效果不佳。
例子
该解决方案需要大量工作,但幸运的是我已经为您创建了必要的类,以及如何在您自己的项目中使用它们的完整示例。代码可在GitHub上找到。
结果
提供的示例产生以下结果:
推荐阅读
- php - PHP 工匠返回拒绝访问 Laravel 中的数据库连接
- java - Spring Boot 应用程序的 Spark 上下文问题
- c# - Webapi 的正确语法
- c - 关于基于标准的 MPI 非阻塞细节的问题
- java - 为什么我的数据报包响应不完整?
- vba - 如何根据标题而不是位置将新列添加到表中?
- loopbackjs - 将 non-db、non-rest loopback 连接器连接到 Loopback 4
- typescript - “‘对象’类型可分配给极少数其他类型。”
- docker - Docker ExpressJS 公用文件夹卷
- asp.net-core-webapi - 在相同的解决方案问题中使用 create-react-app 前端创建 .NET Core 3.0 WebAPI 时出错