繁体   English   中英

为什么在QPinterButton :: paintEvent之后跟QPainter :: fillRect导致应用程序崩溃?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM