1 Attachment(s)
Painting / moving in a single step to avoid flickering
As it was not related to an ARGB widget and there is no answer, I start a new short thread to know if there is a solution to this problem.
I will take the shaped clock sample to explain. I've attached the modified code to this message.
Here is what I've had in the shapedclock.h :
Code:
protected:
private:
int step; // <==
Here is what I've had in the shapedclock's constructor
Code:
setWindowTitle(tr("Shaped Analog Clock"));
step = 0; // <==
this->timer.start(200, this); // <==
Here is the added timerEvent() method :
Code:
{
if(event->timerId() == timer.timerId())
{
++step;
resize(width() + step, height() + step);
update();
}
else
}
And finally, here is the added line in resizeEvent for moving the widget on screen :
Code:
{
move(x() - 5, y() - 5);
And you will see clearly the clock shaking when resizing / moving.
As I told in my previous post, there is a simple way to deal with it. Defining a larger size QWidget and painting at the correct location. But for a very large widget that can grow by more than 3 times its size and can be shifted by more than 2 times its size, it consume much more memory and perhaps it won't be efficient to deal with a large QWidget even if it contains reserved transparency areas for growing / offseting ?
So, do you think there is a way to paint and move in a single step to avoid dealing with a very large QWidget just to solve this shaking motion ?
Thanks for your answer on this very tricky problem.
Re: Painting / moving in a single step to avoid flickering
If you resize a widget and then move it (as move schedules another event) then it's obvious that it will flicker, especially if it's repainted in the meantime. You have to make sure it is repainted after you move it. Instead of resize() you might have used setGeometry() and everything would be fine - the widget would be resized and moved in one go. Sending a move event instead of calling move() might also work. This way it would be executed before the scheduled paint event.
Re: Painting / moving in a single step to avoid flickering
Thanks for your answer.
Anyway, I've tried a setGeometry() with the shaped clock sample previously attached and I had no luck with it. It is flickering as well.
Qt still does it in two steps even if you make a single function call.
Re: Painting / moving in a single step to avoid flickering
I think this is a problem with the window manager and not Qt. On WinXP for instance, you will get this behaviour on any window, when you resize it by the upper left corner.
See also http://labs.trolltech.com/blogs/2007...f-all-flicker/
Re: Painting / moving in a single step to avoid flickering
Thanks for the link spud. But I wonder if it is really the same problem here. Shaped clock is a single widget without childs. But perhaps the QT solution cover too this painting / moving aspect.
Re: Painting / moving in a single step to avoid flickering
None the less, I think it's a symptom of the same problem. Think about it: When you move a window, the WM repaints the window without calling paint(). When you move and resize a window first the WM repaints the window on the new position with the old size, then you repaint it in paint() with the new size. This will lead to flicker. Non rectangular windows only make the problem more noticable.
P.S. You're right. Qt's new approach won't help in this case
Re: Painting / moving in a single step to avoid flickering
Hi,
This is time to give feedback on this problem.
As I said in the another post ( http://www.qtcentre.org/forum//forum...uote=1&p=59426 ), I was dealing with UpdateLayeredWindow() to solve the flickering problem but I was out-of sync with childs events.
In fact, the approach work perfectly !!! My code was quite wide and complex and in a particular place, I was doing a Qt move() call without repainting my widget (so without calling UpdateLayeredWindow()) but I didn't update my private widget members holding the coordinates so later during a repaint, all the pos / mouseEvents for child widgets were out-of-sync.
So, you could deal with the problem if you have such one with UpdateLayeredWindow() (or equivalent non-layered native paint method).
The dark side is this is not multi-platorm so you should play with ifdef and find similar native paint methods on OS X and Linux.
Here is a code sample :
Code:
{
protected:
private:
int myWidgetX; // <==
int myWidgetY; // <==
updateAlpha();
}
{
// Code for painting on a QPixmap rather than on screen
...
// If a move is needed with the resizing of the widget, no move there
// but update of the private integers, it will be synced in the native call
myWidgetX = newXPos; // <==
myWidgetY = newXPos; // <==
// Native call to handle semi-transparency on win32 (with the wonderful cheat for move&resize in one go)
updateAlpha()
}
{
// Let's suppose the widget should be moved but a repaint is not needed
// calling Qt move() but DON'T FORGET to update myWidgetX & myWidgetY to avoid OUT-OF-SYNC
// move(newXPos, newXPos); <= bad if you forget to update myWidgetX&Y
myWidgetX = newXPos; // <==
myWidgetY = newXPos; // <==
move(myWidgetX, myWidgetY); // real Qt move(), I don't need to do repaint there
}
void MyWidget::updateAlpha()
{
HBITMAP oldBitmap;
HBITMAP hBitmap;
SIZE size;
size.cx = widgetMask.width();
size.cy = widgetMask.height();
HDC screenDc = GetDC(NULL);
POINT pointSource;
pointSource.x = 0;
pointSource.y = 0;
POINT topPos;
topPos.x = myWidgetX; // <==
topPos.y = myWidgetY; // <==
HDC memDc = CreateCompatibleDC(screenDc);
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = alpha;
blend.AlphaFormat = AC_SRC_ALPHA;
hBitmap
= widgetMask.
toWinHBITMAP(QPixmap::PremultipliedAlpha);
oldBitmap = (HBITMAP)SelectObject(memDc, hBitmap);
UpdateLayeredWindow(winId(), screenDc, &topPos, &size, memDc, &pointSource, 0, &blend, ULW_ALPHA);
ReleaseDC( NULL, screenDc);
if (hBitmap!=NULL)
{
SelectObject(memDc, oldBitmap);
DeleteObject(hBitmap);
DeleteObject(hBitmap);
}
DeleteDC(memDc);
move(myWidgetX, myWidgetY); // <==
}
Before finding my mistake on the out-of-sync problem, I have made a suggestion to TrollTech but it's still usefull so I hope that TrollTech will add a Qt way of doing it without dealing with native paint methods (except if I really need alpha-transparency top-level support on Windows).
This is the task 194678 on the task-tracker : http://trolltech.com/developer/task-tracker but no news for it at the moment...