Qt Beginner QPainter and QRect

Ash picture Ash · Dec 31, 2012 · Viewed 42.5k times · Source

How would I go about drawing a rectangle?

I have tried two different ways;

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

Which works fine (even though the parameter is not named nor used), but I don't want to use the QPaintEvent * I have no use for it.

So I tried just renaming my function;

void MyWidget::draw()
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

This doesn't display anything (yet has no errors).

Why would it not work if I don't use QPaintEvent * ??

Answer

jdi picture jdi · Dec 31, 2012

The paint event is the method that is called by the paint system when a widget needs to be redrawn. That is why simply naming your own method does not work. It is never called by the paint system.

You really should be using the QPaintEvent. It gives you the rect that needs to be drawn. This rect will be based upon the size of the widget, so instead of using an explicit rect in your paint event, set your widget to the right size. A paint event will be generated should your widget ever move, resize, etc.

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

Now if you want to separate your paint logic into another method, that is fine. But you would need to have it called from the paint event:

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    draw(rect);
}

void MyWidget::draw(QRect &rect)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

If you want to completely bypass the paint events as you said, and only want to create a static rectangle to display, one way is to just draw it once to a pixmap and display it in a QLabel:

QPixMap pix(200,100);
QPainter painter(&pix);
// do paint operations
painter.end()
someLabel.setPixmap(pix)