3

Im trying to draw simple board on my widget.

When I'm trying to automatize this, my paintEvent crashes. I think it is caused by for loop inside, am I right? How to paint it in other way?

void Widget::paintEvent(QPaintEvent *event)
{
QPixmap myPix( QSize(20,20) );
QPainter painter(this);
for(int i = 0; i < 100; i+5){
    painter.drawLine(QPointF(i,0),QPointF(i,max));
}
this->setPixmap(myPix);
}
Iuliu
  • 4,001
  • 19
  • 31
Tatarinho
  • 754
  • 2
  • 11
  • 31
  • Are you defining `max` somewhere, or have you accidentally passed the address of a function to QPointF? – RobH Nov 19 '14 at 11:35
  • 3
    I think `this->setPixmap(myPix);` produces a recursive call of your paint event. – vahancho Nov 19 '14 at 11:35
  • Yes, max is just some float value, i set it when i'm loading some data from text file, it just max height of widget. I deleted this line with setPixmap but it didn't help (generally I deleted declaration of myPix too :) ) – Tatarinho Nov 19 '14 at 11:41
  • @vahancho I think that I should disagree with you, I added explanation in my answer why setPixmap in paintevent does not produce infinite recursive. – Jablonski Nov 19 '14 at 12:28
  • @Chernobyl, nice, but your answer does not seem to explain why this code crashes. – vahancho Nov 19 '14 at 12:50
  • @vahancho Why? First lines of my answer `i+=5` instead of `i+5` Loop is wrong. OP agree with this – Jablonski Nov 19 '14 at 12:51
  • @Chernobyl, Ah, I see now. Sorry. Still the infinite loop... – vahancho Nov 19 '14 at 12:53

1 Answers1

6

Your for loop is incorrect and causes the program crash (I'm sure that's not your fault here). It should be written like this:

for(int i = 0; i < 100; i+=5){
    p.drawLine(QPointF(i,0),QPointF(i,max));
}

i.e. with an assignment of the increment. This way it will do the job and finish properly.

On a side note, I would suggest to use drawPixmap() instead of setPixmap(). But setPixmap() will not cause infinite recursion and for example next code works properly.

//...
this->setPixmap(QPixmap("G:/2/qt.jpg"));
QLabel::paintEvent(event);

Why? With this approach infinite recursion is never produced (see here):

If you call repaint() in a function which may itself be called from paintEvent(), you may get infinite recursion. The update() function never causes recursion.

Indeed setPixmap() calls update(), not repaint(). To prove that see source code:

setPixmap source:

void QLabel::setPixmap(const QPixmap &pixmap)
{
    Q_D(QLabel);
    //...
    d->updateLabel();//what it does?
}

updateLabel source:

void QLabelPrivate::updateLabel()
{
    Q_Q(QLabel);
    //...
    q->updateGeometry();
    q->update(q->contentsRect());//not repaint

}

As I said it is not a mistake but I think that it will be better if you will do all what you need with QPainter.

Jablonski
  • 18,083
  • 2
  • 46
  • 47
  • It works! My God, why I didn't see this on my own. Thanks anyway! – Tatarinho Nov 19 '14 at 12:05
  • I wonder if it is possible to obtain such a board as the background of the widget instead of repaint it in paintEvent? – Tatarinho Nov 19 '14 at 13:55
  • You say *I would suggest to use drawPixmap() instead of setPixmap()*, but in your code snippet you have `this->setPixmap(..)`.. thats a little confusing.. is that a mistake? – thuga Nov 19 '14 at 13:58
  • @thuga As you can see, my answer was edited, you can see my previous (unedited) answer(see edit history), it has no perfect grammar, but it was clear. I did not see that my answer was edited not correctly, so I edited it. Main idea was to prove that setPixmap inside paintEvent does not cause recursive paint – Jablonski Nov 19 '14 at 14:04
  • @Tatarinho See this please: http://qt-project.org/doc/qt-4.8/qwidget.html#paintEvent Pay your attention on setPalette. As you can see, you should use paintEvent or methods like setPixmap, setPalette and so on. – Jablonski Nov 19 '14 at 14:10