简体   繁体   English

无法在自定义QWidget(Qt5)的paintEvent中使用QPainter

[英]Can't use QPainter in paintEvent of custom QWidget (Qt5)

The error in question is as follows: 有问题的错误如下:

QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
QPainter::setFont: Painter not active

After looking at a ton of online forum posts that all came down to people making the same mistake of trying to paint on their widgets outside of paintEvent(), I've been unable to have any luck. 看了无数的在线论坛帖子后,所有人都犯了同样的错误,他们试图在paintEvent()之外的窗口小部件上绘画,但我一直没有运气。 I tried drawing directly on this custom QWidget subclass, I've tried making a child QWidget and drawing on that. 我尝试直接在此自定义QWidget子类上进行绘制,我尝试制作一个子QWidget并在其上进行绘制。 Can someone please show me what thing I'm (probably obviously to someone else) doing wrong? 有人可以告诉我我做错了什么吗?

Thanks in advance. 提前致谢。

Header: 标题:

#ifndef TEXTDISPLAY_H
#define TEXTDISPLAY_H

#include <QWidget>

class TextDisplay : public QWidget
{
    Q_OBJECT

public:
    TextDisplay(QString text, QString fontFamily = "Helvetica", int fontSize = 20,
                int fontColor = Qt::black, QWidget* parent = 0);

protected:
    void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE;
    void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;

private:
    QString text;
    QString fontFamily;
    int fontSize;
    int fontColor;
};

#endif // TEXTDISPLAY_H

Cpp: CPP:

#include "textdisplay.h"
#include <QPainter>


TextDisplay::TextDisplay(QString text, QString fontFamily, int fontSize,
                         int fontColor, QWidget* parent)
    : QWidget(parent), text(text), fontFamily(fontFamily),
      fontSize(fontSize), fontColor(fontColor)
{
    this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
}

void TextDisplay::resizeEvent(QResizeEvent*) {
    paintEvent(NULL);
}

void TextDisplay::paintEvent(QPaintEvent *) {
    QPainter painter(this);
    painter.setPen(fontColor);
    painter.setFont(QFont(fontFamily, fontSize));

    QRect rect(QPoint(0, 0), this->size());
    QRect bound;
    QTextOption options;
    options.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

    painter.drawText(rect, Qt::TextWordWrap | Qt::TextWrapAnywhere, text, &bound);

    this->setMinimumHeight(bound.size().height());
}

Edit with solution: 使用解决方案进行编辑:

Thanks to both responders - I needed to do two things to get it working: 感谢两位响应者-我需要做两件事才能使其正常工作:

a) Get rid of paintEvent(NULL) . a)摆脱paintEvent(NULL) I got rid of the resizeEvent override as well, it was unnecessary as suggested. 我也摆脱了resizeEvent覆盖,这是没有必要的建议。

b) Set a minimum size for the widget. b)设置小部件的最小尺寸。 Without this, the paintEvent was never called by Qt. 没有这个,Qt永远不会调用paintEvent。

If you want to schedule a redraw for your widget, just call update() . 如果要为小部件安排重绘,只需调用update()

If you need an immediate repaint ( which you almost never need ) you can call repaint() instead. 如果需要立即重绘( 几乎不需要 ),则可以调用repaint()

Calling paintEvent() directly will not work -- Qt needs to prepare the backing store to handle the painting, so you can't bypass the update mechanism. 直接调用paintEvent()将不起作用-Qt需要准备后备存储以处理绘画,因此您不能绕过更新机制。 Instead, call the methods above, which will result in a call to paintEvent() (if the widget is visibile, not occluded, etc.etc.etc.). 相反,请调用上述方法,这将导致对paintEvent()的调用(如果窗口小部件可见,未被遮挡等,等等)。

Note also that you should not need to reimplement resizeEvent() just to update your widget. 还要注意,您不必只重新实现resizeEvent()就可以更新窗口小部件。 That should already be done for you by Qt... Qt应该已经为您完成了...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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