4

I'm trying to write a GUI that paints a graph onto it in C++. I am getting a list of errors, all of which say: "QPainter::begin: Widget painting can onnly begin as a result of a paintEvent" Nothing appears to be painting.

main.cpp

#include <QApplication>
#include <QFont>
#include <QPushButton>
#include <iostream>

using namespace std;

#include "skewNormal.h"
#include "ui.h"

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    Window w;
    #if defined(Q_OS_SYMBIAN)
    w.showMaximized();
    #else
    w.show();
    #endif
    return app.exec();
}

ui.h

#ifndef UI_H_INCLUDED
#define UI_H_INCLUDED
#include <QtGui/QMainWindow>

class Window : public QWidget
{
    public:
    Window();

    void paintEvent ( QPaintEvent * event );
};



#endif // UI_H_INCLUDED

ui.cpp

#ifndef GRAPHPN3670_H
#define GRAPHPN3670_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QPaintEvent>
#include <QtGui/QGraphicsView>
#include <QtGui/QHeaderView>
#include <QtGui/QMainWindow>
#include <QtGui/QMenuBar>
#include <QtGui/QStatusBar>
#include <QtGui/QWidget>
#include <QtCore/QRect>
#include <iostream>

using namespace std;

#include "ui.h"
#include "skewNormal.h"

Window::Window()
{
    cout<<"Hello1";
}

void Window::paintEvent ( QPaintEvent * event ){
    cout<<"Hello from paint event";
    QPainter p(this);
    int xL = -width() / 2;
    int yL = 0;
    for(int x = -width() / 2; x < width() / 2; x++)
    {
        int y = getSkewNormal(0.5, x);
        p.drawLine(xL + width() / 2, height() - yL, x + width() / 2, height() - y);
        xL = x;
        yL = y;
    }
}

#endif // GRAPHPE3488_H
refuzee
  • 408
  • 4
  • 15
Ryan Amos
  • 5,422
  • 4
  • 36
  • 56
  • You set your application as console application ? without doing this the console won't print any message! – LoSciamano Jun 09 '11 at 19:08
  • @LoSciamano How do I fix that?? – Ryan Amos Jun 09 '11 at 19:39
  • You could do a lot to trim down your example, which would help us (and you) understand what's going on more easily. For starters, a lot of those includes are unnecessary, and you could just use height() and width() directly instead of getWidth() and getHeight(). Also, (I hope) you don't need an include guard in `ui.cpp`. – Steve S Jun 09 '11 at 20:50
  • More than anything, reduce all of the drawing code to a single QPainter::drawLine() call (or something similar) and get that working before you worry about any of your skew code. – Steve S Jun 09 '11 at 20:51
  • Yeah, the skew code works. I've tested it separately. I'll remove it. I just wanted to have everything up there just in case. EDIT: Done! :D – Ryan Amos Jun 09 '11 at 20:53
  • No, I mean don't even call it. Change your paintEvent to do nothing except draw a line from one corner of the widget to the opposite corner, and see if that works. – Steve S Jun 09 '11 at 20:56
  • I tried adding a fill rectangle: http://pastie.org/private/vewpsv5mjmj2dkvdcbwva. It doesn't work. – Ryan Amos Jun 09 '11 at 21:06
  • 2
    The default brush (which you appear to be using) has the style `Qt::NoBrush`. – Steve S Jun 09 '11 at 21:08
  • Awesome :D That makes a big black square in the corner, which is what it was supposed to do. Thanks! But now I need to figure out how to do the rest. – Ryan Amos Jun 09 '11 at 21:11
  • @Steve S Score! Thanks, works now. Case closed. Now I just have to work the math. – Ryan Amos Jun 09 '11 at 21:14

4 Answers4

4

From the Qt documentation:

Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent widget attribute is set. On Mac OS X and Windows, you can only paint in a paintEvent() function regardless of this attribute's setting.

Steve S
  • 5,256
  • 1
  • 29
  • 26
3

You're not doing widget painting correctly.

The proper thing way to do it is like this;

// Add this method to your widget class
virtual void paintEvent(QPaintEvent * e)
{
   QPainter p(this);
   // Add all calls to p.drawPoint(), etc here
}

... and that is the only place you should be using QPainter. Then, whenever you want your widget to repaint itself, call update() on your widget, and Qt will call paintEvent() for you shortly afterwards.

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
2

You need to show the window

Window w;
w.show()
return app.exec();
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • Try removing the `show()` from the constructor and call it like @Martin is suggesting. – yasouser Jun 09 '11 at 19:07
  • Yeah, I tried that and noted that in the OP. The result is that the constructor and the rest of the main method are called after the window is closed – Ryan Amos Jun 09 '11 at 19:13
  • I put the updated source in the OP. I get a ton of errors, all saying "QPainter::begin: Widget painting can onnly begin as a result of a paintEvent" – Ryan Amos Jun 09 '11 at 19:51
2

First, call show() as suggested by Martin Beckett. Second, you cannot call paintEvent() yourself. You need to override paintEvent() and do your drawing there. Please see the example I provided in this answer.

Community
  • 1
  • 1
Arnold Spence
  • 21,942
  • 7
  • 74
  • 67
  • Can you take a look at the fix I provided, please? Instead of overriding paintEvent, I simply modified my draw method – Ryan Amos Jun 09 '11 at 19:39
  • That will not work. Running your program should demonstrate that. You cannot draw in the constructor of a widget. – Arnold Spence Jun 09 '11 at 19:45
  • Ok, let me try this again :) Not only can you not do the drawing in the constructor, you cannot do the drawing from any other location or method besides an override of paintEvent(). – Arnold Spence Jun 09 '11 at 20:25
  • Yeah, someone else just explained that. I didn't understand that part. It works now, no error. But it doesn't paint :(. I've updated the OP with the changes. – Ryan Amos Jun 09 '11 at 20:37
  • 1
    Well, maybe you could do something simple in your paintEvent() like draw a line from 0,0 to 100,100 to rule out a problem with your geometry calculations. Maybe try setting the pen color too. – Arnold Spence Jun 09 '11 at 20:54
  • I tried both of those. The result is the same: a grey window. Here's the method: http://pastie.org/private/vewpsv5mjmj2dkvdcbwva. I don't see what's wrong with it, although I bet it's something really dumb. I know it's entering the method because of console output. – Ryan Amos Jun 09 '11 at 21:03