Is it possible to use subj in the same paintEvent without flickering ?
Is it possible to use subj in the same paintEvent without flickering ?
The best way to avoid flickering is to use double buffering - paint to a QPixmap and copy to the screen in the paint event.
What do you need GDI for? You can surely use it to paint on an offscreen device and then convert the result to QImage or QPixmap and render them using QPainter as Johan suggested. I wouldn't mix the two approaches (QPainter and GDI) directly though... Especially in Qt4.
I need gdi for visualizing frame grabber's output. If I try to do it with help of QImage - all is terrible slow. From other side I need to show different graphical and text data over the grabber's capture and it might be useful to do it with QPainter because its cool features.
Maybe you should try to optimise it? Which Qt version are you using? Have you tried tweaking by changing window flags?
1.Originally Posted by wysota
I tried!.. What can be more optimal than just drawing QImage in paintEvent ? (QImage is created with QImage ( uchar * data, int width, int height, Format format ) constructor
over the data, filled up with a thread of acquisition library. And all it was done one time in other place than paintEvent.)
2. Qt 4.1.4
3. I tried Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground, Qt::WA_StaticContents, Qt::WA_PaintOnScreen and setAutoFillBackground(false);
in different combinations. No one was really helpful. (But if I use gdi bitmap functions to paint grabbers's data I have to set Qt::WA_NoSystemBackground and Qt::WA_PaintOnScreen or overload paintEngine() = 0 const in order to not have a flickering)
How do you construct the QImage object?
here is the sample:Originally Posted by wysota
Qt Code:
{ if(o == w) { w = 0; w = that_widget; // due code above it will be called AFTER paintEvent CProImage* const image = acquisitor->getImage(); QTime t; t.start(); img.setNumColors(256); for(int i = 0; i < 256; ++i) qDebug("time: %d", t.elapsed()); // usually from 0 to 16 ms. p.drawImage(0, 0, img); // the most time-consuming operation return true; } return false; }To copy to clipboard, switch view to plain text mode
Last edited by wysota; 5th September 2006 at 09:11. Reason: Added [code] tags
What's the sendEvent() here for?
Some things might be optimised here. You are wasting time creating (and destructing) the image object again and again. I think you should have a single image which you reuse everytime and use QImage::loadFromData() to fill it wih contents.
Also make sure you have Qt::WA_OpaquePaintEvent and Qt::WA_NoSystemBackground attributes set for the widget (I wouldn't expect miracles here, though -- using native painting methods it will probably be much faster).
Edit: Qt docs suggest that using native methods along Qt methods should be safe, you might just need to set some attributes for the widget (like PaintOnScreen for X11).
Last edited by wysota; 5th September 2006 at 09:25.
1. usually eventFilter stands between event emitter and emit receiver. But what if I want to do in eventFilter some operations after event will be processed by receiver ? I such a caseOriginally Posted by wysota
this construction works
"
QWidget *that_widget = w;
w = 0;
QApplication::sendEvent(o, e);
w = that_widget;
"
sendEvent here is for receiver to receive its event.
w = 0 is just prohibits eventFilter to reenter...
btw its not my idea. Somewhere in Qt demos I found such approach and it works.
2. I know I wasting time on creating and destructing, but it is just example, although creating and destruction take only 0-16 ms.
3. I also thought that all must be ok mixing native and qt paint engines and I saw that it works together, but with a great flickering which take place when QPainter just initialized.
here is the one more sample to show the problem
QPainter p;
p.setBackgroundMode(Qt::TransparentMode);
p.setBrush(Qt::NoBrush);
p.begin(w);
p.fillRect(0,0, 60, 100, Qt::blue);
p.end();
HDC hdc = w->getDC();
HBRUSH hBrush = CreateSolidBrush(RGB(0xff,00,00));
int width = w->width();
int height = w->height();
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
FillRect(hdc, &rect, hBrush);
w->releaseDC(hdc);
(window flags are set to
w->setAttribute(Qt::WA_OpaquePaintEvent); // фон становится чёрным, перерисовка кривая
w->setAttribute(Qt::WA_NoSystemBackground); // то же самое
w->setAttribute(Qt::WA_StaticContents); // фон нормальный, перерисовка кривая
w->setAttribute(Qt::WA_PaintOnScreen); //то же самое
w->setAutoFillBackground(false); // то же самое.. если true - аналогично
)
How about just returning false (or better yet BaseClass::eventFilter(o,e)) from the eventFilter() method? It basically forwards the event to the receiver without any additional hacks.Originally Posted by Elder Orb
Edit: Ah... I missed the word "after". I'd use a timer with 0 timeout here instead. BTW. Why don't you just move all the functionality to the widget itself? You'd end up with a much simpler code.
16ms*25fps = 400ms, so only half of the time remains for showing images with 25fps.2. I know I wasting time on creating and destructing, but it is just example, although creating and destruction take only 0-16 ms.
It is probably clearing the background. You must be missing a proper attribute.3. I also thought that all must be ok mixing native and qt paint engines and I saw that it works together, but with a great flickering which take place when QPainter just initialized.
You must be missing the proper combination here. When do you set those attributes? Before "w" is shown or afterwards?w->setAttribute(Qt::WA_OpaquePaintEvent); // фон становится чёрным, перерисовка кривая
w->setAttribute(Qt::WA_NoSystemBackground); // то же самое
w->setAttribute(Qt::WA_StaticContents); // фон нормальный, перерисовка кривая
w->setAttribute(Qt::WA_PaintOnScreen); //то же самое
w->setAutoFillBackground(false); // то же самое.. если true - аналогично
)
Last edited by wysota; 5th September 2006 at 14:22.
Agree. But sometimes I just too lazy to subclassHow about just returning false (or better yet BaseClass::eventFilter(o,e)) from the eventFilter() method? It basically forwards the event to the receiver without any additional hacks.
Edit: Ah... I missed the word "after". I'd use a timer with 0 timeout here instead. BTW. Why don't you just move all the functionality to the widget itself? You'd end up with a much simpler code.
I've tried to get out all besides "painter.drawImage(&image);" from the paintEvent but it was still too slow. btw I unsure that grabber makes a frame ready (callback function to trigger) with a frequancy 25. I have to check it tomorrow, maybe I should skip some frames... Tnx for idea!16ms*25fps = 400ms, so only half of the time remains for showing images with 25fps.
I've tried almost all combinations for all flags I thought important enough (those 4 flags). I just don't know what to try else..It is probably clearing the background. You must be missing a proper attribute.
You must be missing the proper combination here. When do you set those attributes? Before "w" is shown or afterwards?
You'd achieve better results, some function calls would be omitted.Originally Posted by Elder Orb
In general I would first calculate the frequency of updates (fps) and then I'd use a timer set to timeout according to this frequency. Then, in the timeout slot I would grab a frame which needs to be displayed now (you'll probably have to skip a frame now and then), I'd store a ready image and then call update() to repaint the widget. The paint event would just have to render the widget. You just have to find a way to calculate how many frames should be skipped (you can probably to that by substracting times of subsequent timeouts as the timeouts won't be exactly as you set them -- they'll be not more often than what you set).I've tried to get out all besides "painter.drawImage(&image);" from the paintEvent but it was still too slow. btw I unsure that grabber makes a frame ready (callback function to trigger) with a frequancy 25. I have to check it tomorrow, maybe I should skip some frames... Tnx for idea!
Try using OpenGL. Use a QGLWidget and draw images as textures (I think that's the way it is usually done, others might know better, I've never tried this). As OpenGL is (probably) hardware accellerated, this should go much faster and you'll waste less CPU cycles for that and with a good graphics cards you get different "manipulations" of the movie for free -- you'll be able to rotate, mirror, fade, crop, resize, colorise, etc. without much effort, you can even display your move as a rotating cube And you should definitely buffer a number of frames ahead. I'm sure your gfx board will be able to store more than one texture at a timeI've tried almost all combinations for all flags I thought important enough (those 4 flags). I just don't know what to try else..
I'm sorry , but i've missed you last reply and see it just now . Although I've solved my problem with a low-level win api calls (without QPainter at all), I stiil interesting in pure-qt solution. Some time ago I tried QGLWidget, but probably did it in a wrong way, because no acceleration has been acquired... I didn't know about gl functions using, so I used QPainter (which in gl widget must be gl-accelerated ? ).. What should I do to achieve opengl-accelerated QImage output ?
Bookmarks