簡體   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