Results 1 to 14 of 14

Thread: gdi and QPainter

  1. #1
    Join Date
    Jan 2006
    Posts
    30
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default gdi and QPainter

    Is it possible to use subj in the same paintEvent without flickering ?

  2. #2
    Join Date
    Jan 2006
    Location
    Alingsås, Sweden
    Posts
    437
    Thanks
    3
    Thanked 39 Times in 39 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: gdi and QPainter

    The best way to avoid flickering is to use double buffering - paint to a QPixmap and copy to the screen in the paint event.

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: gdi and QPainter

    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.

  4. #4
    Join Date
    Jan 2006
    Posts
    30
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: gdi and QPainter

    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.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: gdi and QPainter

    Maybe you should try to optimise it? Which Qt version are you using? Have you tried tweaking by changing window flags?

  6. #6
    Join Date
    Jan 2006
    Posts
    30
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: gdi and QPainter

    Quote Originally Posted by wysota
    Maybe you should try to optimise it? Which Qt version are you using? Have you tried tweaking by changing window flags?
    1.
    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)

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: gdi and QPainter

    How do you construct the QImage object?

  8. #8
    Join Date
    Jan 2006
    Posts
    30
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: gdi and QPainter

    Quote Originally Posted by wysota
    How do you construct the QImage object?
    here is the sample:
    Qt Code:
    1. bool mvsstand::eventFilter(QObject *o, QEvent *e)
    2. {
    3. if(o == w) {
    4. if(e->type() == QEvent::Paint) {
    5.  
    6. QWidget *that_widget = w;
    7. w = 0;
    8. QApplication::sendEvent(o, e);
    9. w = that_widget;
    10.  
    11. // due code above it will be called AFTER paintEvent
    12.  
    13. CProImage* const image = acquisitor->getImage();
    14.  
    15. QTime t;
    16. t.start();
    17.  
    18. QImage img((uchar*)image->GetData(), image->GetWidth(), image->GetHeight(), QImage::Format_Indexed8);
    19. img.setNumColors(256);
    20. for(int i = 0; i < 256; ++i)
    21. img.setColor(i, QColor(i, i, i).rgb());
    22.  
    23. QPainter p(w);
    24.  
    25. qDebug("time: %d", t.elapsed()); // usually from 0 to 16 ms.
    26.  
    27. p.drawImage(0, 0, img); // the most time-consuming operation
    28.  
    29. return true;
    30. }
    31. return false;
    32. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by wysota; 5th September 2006 at 09:11. Reason: Added [code] tags

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: gdi and QPainter

    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.

  10. #10
    Join Date
    Jan 2006
    Posts
    30
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: gdi and QPainter

    Quote Originally Posted by wysota
    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).
    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 case
    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 - аналогично
    )

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: gdi and QPainter

    Quote Originally Posted by Elder Orb
    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 case
    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.
    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.

    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.

    2. I know I wasting time on creating and destructing, but it is just example, although creating and destruction take only 0-16 ms.
    16ms*25fps = 400ms, so only half of the time remains for showing images with 25fps.

    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.
    It is probably clearing the background. You must be missing a proper attribute.
    w->setAttribute(Qt::WA_OpaquePaintEvent); // фон становится чёрным, перерисовка кривая
    w->setAttribute(Qt::WA_NoSystemBackground); // то же самое
    w->setAttribute(Qt::WA_StaticContents); // фон нормальный, перерисовка кривая
    w->setAttribute(Qt::WA_PaintOnScreen); //то же самое
    w->setAutoFillBackground(false); // то же самое.. если true - аналогично
    )
    You must be missing the proper combination here. When do you set those attributes? Before "w" is shown or afterwards?
    Last edited by wysota; 5th September 2006 at 14:22.

  12. #12
    Join Date
    Jan 2006
    Posts
    30
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: gdi and QPainter

    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.

    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.
    Agree. But sometimes I just too lazy to subclass


    16ms*25fps = 400ms, so only half of the time remains for showing images with 25fps.
    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!


    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?
    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..

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: gdi and QPainter

    Quote Originally Posted by Elder Orb
    Agree. But sometimes I just too lazy to subclass
    You'd achieve better results, some function calls would be omitted.

    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!
    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 almost all combinations for all flags I thought important enough (those 4 flags). I just don't know what to try else..
    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 time

  14. #14
    Join Date
    Jan 2006
    Posts
    30
    Qt products
    Qt3 Qt4
    Platforms
    Windows

    Default Re: gdi and QPainter

    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.