PDA

View Full Version : Freeze using QTimer with interval 0



Alundra
27th May 2013, 15:53
Hi all,
I have a class who inherit from QWidget to render a 3D content inside.
I use a QTimer to refresh the window like that :


m_Timer.setInterval( 0 );
connect( &m_Timer, SIGNAL( timeout() ), this, SLOT( repaint() ) );
m_Timer.start();

When I launch the application and I move the window, the application freeze.
When I undock a dock window and I try to move it, the application freeze.
The only one solution I have is to set the interval to 10ms.
Thanks for the help

wysota
27th May 2013, 17:19
Use update() instead of repaint(). Besides, what is the point of constantly updating the widget if nothing in it changes? Redraw only when the scene is updated.

zeeshanaayan07
27th May 2013, 17:44
great coding Freeze using QTime with interval

Alundra
27th May 2013, 19:44
using update() instead of repaint() doesn't change anything, still freeze.

wysota
27th May 2013, 20:29
Please provide a minimal compilable example reproducing the problem.

Alundra
27th May 2013, 23:28
#include <QMainWindow>
#include <QDockWidget>
#include <QApplication>
#include <QTimer>

class TestWidget : public QWidget
{
public:

TestWidget(QWidget* parent = 0) :
QWidget(parent),
m_Initialized(false)
{
m_Timer.setInterval(0);
}

QPaintEngine* paintEngine() const
{
return NULL;
}

void showEvent(QShowEvent* event)
{
if(m_Initialized == false)
{
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(repaint()));
m_Timer.start();
m_Initialized = true;
}
}

private:

QTimer m_Timer;
bool m_Initialized;
};

class MainWindow : public QMainWindow
{
public:

MainWindow(QWidget* parent = 0) :
QMainWindow(parent)
{
QDockWidget* NewDock = new QDockWidget("Test", this);
NewDock->setWidget(new TestWidget(this));
addDockWidget(Qt::BottomDockWidgetArea, NewDock);
}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

wysota
28th May 2013, 00:57
What is returning an empty paint engine meant to do in this example? What exactly would you expect to receive in the widget?

ChrisW67
28th May 2013, 01:01
Doesn't freeze here, not that it actually does anything useful. It does, however, tie up a CPU core at near 100% utilisation... but then that is what you are asking it to do with a zero timer.

Alundra
28th May 2013, 01:52
The real widget in the application initialize a render window from a 3D Engine.
The return NULL is to remove the flickering.
To reproduce the freeze you have to undock and move the dock or the application window.

wysota
28th May 2013, 02:26
No freeze here... sorry...

Did you check that the small code snippet that you posted actually freezes?

Alundra
28th May 2013, 02:53
I have retested again and the freeze is real and not on this computer only.
Only try to move the window and the freeze will be there.
I have to ctrl+alt+enter to end the application.

wysota
28th May 2013, 08:06
Which platform did you test it on? Which Qt version?

Alundra
28th May 2013, 09:02
I use QT 5.0.2.
On my laptop using windows 8 I don't have the freeze, but on windows 7 I have the freeze.

Alundra
29th May 2013, 01:29
Do you have a workaround to update the widget without a timer and who works for all platform ?

ChrisW67
29th May 2013, 03:32
As Wysota said, when the data that is driving whatever you display in the widget changes, call update() and make sure you program does not block the Qt event loop. It really is that simple and it's not a "workaround". If the data changes every millisecond then you might need to be a bit smarter about how often you update() the widget.

You have not shown us anything that might drive the widget content so I don't see how we can be specific.


BTW: I just built your code with Qt 5.0.1 on Windows 7 32-bit. No hanging, lockups etc. It does sit, as expected, on near 100% CPU.

Chris Lux
6th August 2013, 11:30
Hi,
I have the same issue. The sample code provided in this thread clearly displays my use case (do not care about the 100% CPU load, it should just trigger rendering frames as fast as possible!).

The problem was introduced in my case with Qt 4.8.2. I run my software under Windows compiled as x64 code and I found the following cases:

Windows 7 Aero enabled -> freeze on window move
Windows 7 classic desktop -> no problem
Windows 8 (DWM enabled by default) -> no problem

I tried different ways to refresh the widget such as calling update() at the end of paintEvent() to schedule another frame, but the behavior at the end remains the same. This seems to be a bug in Qt. There is NO way to continuously refresh a rendering widget anymore.

Does anyone else noticed this behavior introduced sometime around Qt 4.8.x and does there exist a workaround?

wysota
6th August 2013, 12:38
The problem is with Windows event handling. When you move a window around by dragging, events are not delivered to this window.

Chris Lux
6th August 2013, 13:26
Hi,
thanks for the answer, but how does this affect the Aero/non-Aero case and how can it be solved. It worked before and still is a default case as proposed by Qt itself.

wysota
6th August 2013, 14:47
thanks for the answer, but how does this affect the Aero/non-Aero case and how can it be solved.
Aero is Windows desktop compositor. It is (probably) the component responsible for the problem.

Chris Lux
6th August 2013, 15:02
this does not explain why it was working prior to Qt 4.8.x with the same Windows installation and drivers.

wysota
6th August 2013, 15:30
No, it doesn't. It also doesn't explain why I've known this problem from much earlier versions than 4.8.2.

Chris Lux
7th August 2013, 08:50
Could you elaborate on the problem please.

I am not able to reproduce it with plain Win32 tests (InvalidateRect called to force window refresh).

(just to point out, I am coding qt since version 2.x and Win32 for 13years now, so please provide some technical explanations where the problem lies...)

wysota
7th August 2013, 14:13
I have no idea where the problem lies. I only know that it is present -- search the forums and see for yourself.