为啥 QPainter 可能会拒绝在paintEvent 中工作?

Posted

技术标签:

【中文标题】为啥 QPainter 可能会拒绝在paintEvent 中工作?【英文标题】:Why QPainter might reject to work inside paintEvent?为什么 QPainter 可能会拒绝在paintEvent 中工作? 【发布时间】:2012-11-21 21:27:31 【问题描述】:

我有:

class QTextEditEnter : public QTextEdit

    Q_OBJECT
public:
    QTextEditEnter( QWidget *_parent ) : QTextEdit(_parent)
    
        this -> setFrameStyle( QFrame::Sunken ); // Sunken!
    

protected:
    virtual void keyPressEvent(QKeyEvent * event);
    virtual void paintEvent(QPaintEvent *_event)
    
        QTextEdit::paintEvent( _event );
        QPainter pnt(this);
        pnt.setPen( QColor( 0, 0, 0, 0xff ));
        pnt.drawRect( 0, 0, width(), height());
    

    signals:
        void signalPressEnter();
;

给出:

QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::setPen: Painter not active
QPainter::drawRects: Painter not active
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::setPen: Painter not active
QPainter::drawRects: Painter not active

为什么会这样?

更新

// QPainter( this )
// QTextEdit::paintEvent at the begining of custom PaintEvent
// RESULT: "QPainter::begin: Widget painting can only begin as a result of a paintEvent" ...
virtual void paintEvent(QPaintEvent *_event)

    QTextEdit::paintEvent( _event );
    QPainter pnt( this );
    pnt.setPen( QColor( 0, 0, 0, 0xff ));
    pnt.drawRect( 0, 0, width()-1, height()-1);


// QPainter ( viewport() )
// QTextEdit::paintEvent at the begining of custom PaintEvent
// RESULT: works.
virtual void paintEvent(QPaintEvent *_event)

    QTextEdit::paintEvent( _event );
    QPainter pnt( viewport() );
    pnt.setPen( QColor( 0, 0, 0, 0xff ));
    pnt.drawRect( 0, 0, width()-1, height()-1);


// *** BONUS ***
// QPainter( viewport() ) or QPainter ( this )
// QTextEdit::paintEvent after QPainter() constructor.
// RESULT: Segmentation fault.
virtual void paintEvent(QPaintEvent *_event)

    QPainter pnt( viewport() );
    pnt.setPen( QColor( 0, 0, 0, 0xff ));
    QTextEdit::paintEvent( _event ); // WRONG PLACE!!!
    pnt.drawRect( 0, 0, width()-1, height()-1);

【问题讨论】:

您似乎在某处明确调用QTextEditEnter::paintEvent()。会是这样吗?它只能由 Qt 从事件循环中直接调用。 Tilman Vogel 我认为没有 - 没有找到任何直接调用它的方法。 您可以在调试模式下跟踪您的程序,并检查它是否输出此类消息。请向我们提供更多信息。 @troyane o... 我对调试此类代码不友好,尤其是在 linux 中,这发生在我的案例中 :) 简而言之。您必须将构建类型(从发布)更改为调试,然后在代码中添加断点,然后运行 ​​(F5)。使用调试控件(步入、跨步)实时跟踪您的代码。祝你好运! 【参考方案1】:

代替

QPainter pnt(this);

试试

QPainter pnt(viewport());
pnt.setPen(QColor( 0, 0, 0, 0xff ));
pnt.drawRect(viewport()->rect());

viewport() 是可绘制区域,可能是导致问题的原因

【讨论】:

谢谢!这有帮助! viewport() 是 QAbstractScrollArea 的一种方法(我记得),但在普通 QWidget 中不存在。如果你继承 QTextEdit,你必须记住使用“viewport()”,而不是“this”。这很奇怪,因为你必须记住它......

以上是关于为啥 QPainter 可能会拒绝在paintEvent 中工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在paintEvent之外获取QPainter的字体度量?

Qt学习之路(24): QPainter(改写paintEvent)

Qt paintEvent事件 显示图片文字

paintEvent中的Qt QPainter消除了用paintGL绘制的图形

使用 QPainter 和 paintEvent 在 PYQT5 中的 QLabel 中包含的 Pixmap 上绘制圆圈

Qt - 创建 QPainter