[英]Why the application crashes when QPushButton::paintEvent is followed by QPainter::fillRect?
我通过子类化QPushButton
并处理paintEvent
实现圆形按钮。 我想显示用户设置的文本,然后画一个圆。
调用QPushButton::paintEvent
方法后,应用程序在QPainter::fillRect
崩溃。 如果未调用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
}
};
如何解决当机问题?
首先创建一个画家,将QPaintDevice *device
传递给QPainter
的构造函数,该构造函数调用 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);
来避免同时拥有两个活动绘画者QPushButton::paintEvent(e);
到CRoundAnimatingBtn::paintEvent
开始(在此事件处理程序中的所有其他内容之前)。
注意:如果您放置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);
}
该示例产生以下结果:
如您所见,文本与您的自定义图形一起显示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.