我正在通过子类QPushButton
和处理paintEvent
来实现圆形按钮。我想显示用户设置的文本,然后画一个圆。
调用QPainter::fillRect
方法后,应用程序在QPushButton::paintEvent
崩溃。如果未调用QPushButton::paintEvent
,则不会崩溃,但不会显示按钮文本。
这是我的代码:
class CRoundAnimatingBtn : public QPushButton
{
Q_OBJECT
public:
explicit CRoundAnimatingBtn(QWidget *parent = nullptr) : QPushButton(parent) {}
protected:
void resizeEvent(QResizeEvent *) { setMask(QRegion(rect(), QRegion::Ellipse)); }
void paintEvent(QPaintEvent * e) {
QPainter painter(this);
QPointF center(width()/2, height()/2);
QRadialGradient radialGradient(center, qMin(width(), height())/2, center);
QPushButton::paintEvent(e); // Application crashes if this is called
if (isDown()) {
radialGradient.setColorAt(0.0,Qt::transparent);
radialGradient.setColorAt(0.79, Qt::transparent);
radialGradient.setColorAt(0.80, Qt::gray);
radialGradient.setColorAt(0.95, Qt::black);
radialGradient.setColorAt(0.90, Qt::gray);
radialGradient.setColorAt(0.91, Qt::transparent);
} else {
radialGradient.setColorAt(0.0,Qt::transparent);
radialGradient.setColorAt(0.84, Qt::transparent);
radialGradient.setColorAt(0.85, Qt::gray);
radialGradient.setColorAt(0.90, Qt::black);
radialGradient.setColorAt(0.95, Qt::gray);
radialGradient.setColorAt(0.96, Qt::transparent);
}
painter.fillRect(rect(), radialGradient); // Application crashes here
}
};
如何修复崩溃?
答案 0 :(得分:1)
您首先创建一个画家,将QPaintDevice *device
传递给QPainter
的构造函数,calls QPainter::begin
:
QPainter painter(this);
然后您将其的基类实现称为
paintEvent
:
QPushButton::paintEvent(e);
在完成第一个涂漆设备之前,它会在相同的涂漆设备上创建一个新的涂漆器QStylePainter p
:
void QPushButton::paintEvent(QPaintEvent *)
{
QStylePainter p(this);
QStyleOptionButton option;
initStyleOption(&option);
p.drawControl(QStyle::CE_PushButton, option);
}
最后,您尝试使用以下方法与第一位画家QPainter painter
进行绘制:
painter.fillRect(rectangle, radialGradient);
重要提示::这种方法是不允许的,因为QPainter::begin
的文档明确指出:
警告:油漆设备一次只能由一位油漆工油漆。
考虑到这一点,我建议您通过将QPushButton::paintEvent(e);
移到CRoundAnimatingBtn::paintEvent
的开头(在此事件处理程序中的所有其他功能之前)来避免同时拥有两个活动的绘画程序。 / p>
注意:如果您将QPushButton::paintEvent(e);
放在CRoundAnimatingBtn::paintEvent
的最后,则默认实现会覆盖您的自定义图形,因此将不可见。
CRoundAnimatingBtn::paintEvent
的外观如下:
void paintEvent(QPaintEvent * e) {
QPushButton::paintEvent(e);
QPainter painter(this);
QPointF center(width()/2, height()/2);
QRadialGradient radialGradient(center, qMin(width(), height())/2, center);
...
painter.fillRect(rect(), radialGradient);
}
该示例将产生以下结果:
如您所见,文本与您的自定义图形一起显示。