PDA

View Full Version : QPainter



Misko
29th July 2007, 19:59
Hello,

I'm trying to display a line with QPainter with following code:
drawit.h:


#ifndef DRAWIT_H
#define DRAWIT_H
#include <QWidget>
class DrawIt : public QWidget
{
Q_OBJECT
public:
DrawIt(QWidget *parent = 0);
protected:
QPainter *paint;
};
#endif


drawit.cpp:


#include <QtGui>
#include "drawit.h"
DrawIt::DrawIt(QWidget *parent) : QWidget(parent)
{
paint = new QPainter();
}
void DrawIt::paintEvent(QPaintEvent *)
{
paint->drawLine(10, 10, 50, 50);
}


main.cpp:


#include <QApplication>
#include "drawit.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
DrawIt *drawIt = new DrawIt;
drawIt->show();
return app.exec();
}


This gives the error "no 'void DrawIt::paintEvent(QPaintEvent *)' member function declared in class DrawIt

Where am i making the mistake? :confused:

Thx in advance,
Misko

marcel
29th July 2007, 20:06
You do not declare the paintEvent function in your class. This function is virtual protected in QWidget. In order to reimplement it in your class you also have to declare it.
Add the following snippet to your class declaration:


protected:
void paintEvent(QPaintEvent* );
Also, when you draw that line be careful what coordinates you pass because it is possible to draw off-widget. Depends on the dimensions of the widget.

Also add a forward declare, right before the class declaration, in the header:


class QPaintEvent;
This is needed in order not to include the header in which QPaintEvent is declared. You just tell the compiler that this class is implemented somewhere.

EDIT: you don't need a member QPainter. Just instantiate one in the paint event, on the stack.
This is usually done because the painter state may get corrupted( f.e. remain mirrored from a previous pain event ).
It is better to start with a fresh painter and not to worry about its state.

Regards

jacek
29th July 2007, 20:13
DrawIt::DrawIt(QWidget *parent) : QWidget(parent)
{
paint = new QPainter();
}
Better create that painter in the paintEvent() method and don't forget to pass "this" as a parameter:

void DrawIt::paintEvent( QPaintEvent * )
{
QPainter paint( this );
paint.drawLine(10, 10, 50, 50);
}

As an alternative solution you will have to use QPainter::begin() and QPainter::end().

Misko
29th July 2007, 21:56
@Marcel&Jacek: both thanks!!!
It works now!
I find it a lot more difficult to learn C++ because i'm accustomed to Java.
I find Java more straightforward and thus more easy to learn...
What about you?

Regards,
Misko

marcel
29th July 2007, 22:07
Well, I do both C++ and Java.
C++ is much more flexible and fast, when it comes to writing desktop applications.
On the other hand, while Java may be easier to learn, it is not really the best choice when writing a desktop application(although fully portable). Java is a server side language and it should be treated as such.

Regards

Misko
2nd August 2007, 22:08
Hi again!

i'm trying the same thing (drawing a line on a widget), but now in the QDevelop-IDE.
First I create a new Project with a MainWindow.
Then I see that the MainWindowImpl-constructor has the following:
class QPaintEvent;
class QPainter;
public:
MainWindowImpl(QWidget *parent = 0, Qt::WFlags f = 0);
...
Then I implement a function in MainWindowImpl.cpp that calls MainWindowImpl::paintEvent...
So I assume that it should be OK because the MainWindow inherits from QWidget, but on compiling I receive following error in :
no 'void MainWindowImpl::paintEvent(QPaintEvent *)' member declared in class 'MainWindowImpl'
Apparently MainWindowImpl doesn't inherit the function paintEvent from QWidget?
What could be the solution? :confused:

Regards,
Misko

marcel
2nd August 2007, 22:13
Well, first of all, what you're trying to do is incorrect.
You must not call paintEvent manually, unless you set a specific flag for the widget, that allows it to be painted outside a paint event( I doubt you need that).

In qt4 widgets cannot be painted outside paint events.

To schedule a repaint, you must call update(). This will post a paint event in the widgets event queue, that will be handled when the event loop assumes control.

So, call update instead.

However, to solve your problem, how do you call this function?
Can you post some code?

Regards.

Misko
3rd August 2007, 23:42
Hi Marcel,

I try to draw a polygon on the main widget.
Here's the code i've used. It gave me in the debug-version a segmentation fault...
Poly.h:
#ifndef POLYIMPL_H
#define POLYIMPL_H
#include <QWidget>
#include "ui_poly.h" /* designer made*/
class QPaintEvent;
class QPainter;
class QPolygon;
class PolyImpl::public QMainWindow, public Ui::Poly
{
Q_OBJECT
public:
PolyImpl(QWidget *parent = 0, Qt::WFlags f = 0);
protected:
void paintEvent(QPaintEvent *);
private:
QPainter *painter;
QPolygon polygoon;
};
#endif
polyimpl.cpp:
#include <QtGui>
#include "polyImpl.h"
PolyImpl::PolyImpl(QWidget *parent, Qt::WFlags f)
: QMainWindow(parent, f)
{
setupUi(this);
polygoon << QPoint(10, 10) << QPoint(100, 50) << QPoint(75, 75);
}
void PolyImpl::paintEvent(QPaintEvent *)
{
painter->begin(this);
painter->drawPolygon(polygoon);
painter->end();
}
main.cpp:
#include <QApplication>
#include "polyImpl.h"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
PolyImpl win;
win.show();
app.connect(&app, SIGNAL(lasWindowClosed()), &app, SLOT(quit()));
return app.exec();
}

marcel
3rd August 2007, 23:53
Because you don't instantiate the member QPainter.
You have two options:
1. Add:


painter = new QPainter();

in the constructor, and:


delete painter;

in the destructor.

2. Remove the member( recommended ) and in paint event:


QPainter painter(this);
painter.drawPolygon(polygoon);


Regards

Misko
5th August 2007, 20:23
Thx Marcel!

It works now!
Not easy to work with .(dot) and -> operators in C++.
Better to get a decent C++-manual to read!

Regards,
Misko