Intense drawing with QT

Started by
9 comments, last by Dospro 12 years, 8 months ago
Hi everyone.

I am trying to use QT 4.7 to make an emulator's debugger.
I have been able to solve almost all issues about using QT.

The only problem i have now is about drawing "pixels" into a widget.

I have read countless guides and the official documentation.
I always get ways to draw something that remains static.

I need to redraw the content of the widget fast.
I don't need special hardware acceleration, the normal QT rasterizer is ok, but i don't know how to do it.

Has anyone already done it?
Advertisement
Typically what people do, is they'd have their widget own a QTimer. They'd then connect the QTimer's timeout() signal to a custom repaint() slot, like this:

connect(&myTimer, SIGNAL(timeout()), this, SLOT(repaint()));

You'd set the timer's interval to whatever you want, for a fixed rate. For example, you might have it fire only 30 times a second.
If you're doing an emulator, it might be a good idea to use this as a way to artificially slow down the emulator to something close to the speed of the device you are emulating.

If you just want it to run constantly, pass it a interval of 0. A timer with a interval of 0, according to the documentations, will run as fast as possible without slowing down any input or GUI events.

A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.[/quote]

Typically what people do, is they'd have their widget own a QTimer. They'd then connect the QTimer's timeout() signal to a custom repaint() slot, like this:

connect(&myTimer, SIGNAL(timeout()), this, SLOT(repaint()));

You'd set the timer's interval to whatever you want, for a fixed rate. For example, you might have it fire only 30 times a second.
If you're doing an emulator, it might be a good idea to use this as a way to artificially slow down the emulator to something close to the speed of the device you are emulating.

If you just want it to run constantly, pass it a interval of 0. A timer with a interval of 0, according to the documentations, will run as fast as possible without slowing down any input or GUI events.

A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.


[/quote]

Alright. Actually, that's exactly what i do for the emulator process. I never thought that would work for painting too.
I will try it and see how it gets...

THanks for the help.
Ok. That worked wonderfully.

Now. I'm trying to draw the screen.

I have looked at the QT docs. And it seemes QImage is the best choice.
Still i haven't found a descent example of hoy to do it.

I have my main window application with a menu bar.
And i want the central widget to be the drawing "canvas".

But QT really overcomplicates this by having a lot of widgets which do technically the same thing.(QImage, QPixmap, QPainter......)

Does anyone have any idea what's the optimal and most correct way to so this??
QImage, QPixmap and QPainter aren't widgets! They each have their own, distinct purpose.

Typically you'll create a derived QWidget and override its paintEvent() to do custom rendering of the widget. In here you'll create a QPainter whose methods you call to draw lines, blit images, etc.

The QPainter documentation has links to lots of examples.
Ofcourse, depending on your needs, the best 'canvas' may be a QGraphicsView, using QGraphicsScene and QGraphicsItem. It really depends on what you are doing.
Ok. After more reading of the descriptions of each class i'm still kind of confuse.

What i need is to draw the entire widget(canvas) constantly with pixels.

I already have a buffer with the image to show each frame. I need just to paint what is in the buffer to a widget, and as fast as it can. (At least 60 FPS).

Perhaps QGraphisScrene with QGraphicsView may do the job,(I still have to find out how). But isn't QImage useful here???
Because using QPainter you have to set a pen for each color you want paint. and i have thousands of different pixels with different colors. I don't think this is the optimal way of doing it.

Any suggestion?
A) If you are painting each individual pixel yourself, use QImage, and draw it with QPainter.
B) If you are painting a bunch of images (You loading images from disk), then load them as QPixmap, and paint them with QPainter.
C) If you want QT to handle things like drag-and-drop, or mouse clicks, for each individual image, use a QGraphicsView, and inherit each image from a QGraphicsPixmapItem or a QGraphicsItem.

[hr]
A) If you want your scene to be larger than the size of your widget, so you can scroll around whatever you a drawing with the arrow keys or whatever, and you want QT to handle that scene for you, use QGraphicsView, and make each item a QPixmap, drawn onto the scene with QPainter.
B) If your scene is the same size as your widget, or if you plan to manually handle scrolling, inherit QWidget and override the drawing.

A) If you are painting each individual pixel yourself, use QImage, and draw it with QPainter.
B) If you are painting a bunch of images (You loading images from disk), then load them as QPixmap, and paint them with QPainter.
C) If you want QT to handle things like drag-and-drop, or mouse clicks, for each individual image, use a QGraphicsView, and inherit each image from a QGraphicsPixmapItem or a QGraphicsItem.

[hr]
A) If you want your scene to be larger than the size of your widget, so you can scroll around whatever you a drawing with the arrow keys or whatever, and you want QT to handle that scene for you, use QGraphicsView, and make each item a QPixmap, drawn onto the scene with QPainter.
B) If your scene is the same size as your widget, or if you plan to manually handle scrolling, inherit QWidget and override the drawing.


Ok. but again, With QPainter i have to set the pen for each individual pixel which is not quite efficient. If i have a resolution of 640*480 with 32 bpp each frame, that would be thousands of pen-sets to draw all the pixel for each frame(consider i want to get as far as 60 fps).

Do i really have to use QPainter or is another way?
Thanks for the help

Ok. but again, With QPainter i have to set the pen for each individual pixel which is not quite efficient. If i have a resolution of 640*480 with 32 bpp each frame, that would be thousands of pen-sets to draw all the pixel for each frame(consider i want to get as far as 60 fps).

Do i really have to use QPainter or is another way?
Thanks for the help


Re-read this line:

A) If you are painting each individual pixel yourself, use QImage, and draw it with QPainter.[/quote]

That is to say, create a QImage, and fill the pixels using setPixel().
Alternatively, operate on raw data, then when finished, pass that raw data to a new QImage using this constructor.

If you draw your data more often then the data changes, you might try converting the QImage to a QPixmap using QPixmap::fromImage(), and keeping that QPixmap around until the next time you change your data. But profile it to see if it actually speeds anything up, or just slows it down.

Think of it like this: QImage is a buffer of pixels that QPainter can then draw onto your QWidget. You can either manipulate the buffer through QImage, or you can create your own buffer and manipulate that directly, and then just convert it to a QImage when finished.
Also, if you want extra drawing speed, you can convert the QImage to a QPixmap, but the actual conversion itself may negate any speed benefits you gain, so you have to profile it to see if it actually helps or not.

QPixmap is optimized for really fast drawing. QImage is optimized for image manipulation. QBitmap is only for binary masks, so ignore it. QPicture is for a program like MSPaint where someone is drawing a picture, so you can ignore that to.

Read this (from the Qt documentation):
QImage is designed and optimized for I/O, and for direct pixel access and manipulation, while QPixmap is designed and optimized for showing images on screen.[/quote]

But both QImage and QPixmap image you'll have to then use QPainter to actually draw, once you are done editing the pixels. QPainter::drawImage(), or QPainter::drawPixmap().

This topic is closed to new replies.

Advertisement