由于我需要比Qt更精确的定时器,其分辨率为~15ms,我试图使用来自windows api的QueryPerformanceCounter()来实现我自己的定时器。
我的第一个镜头是继承QObject并构建一个带有无限循环的计时器,每秒触发一次信号。我尝试使用moveToThread()将此计时器移动到其自己的线程,以便它每秒只更新我的主窗口而不会阻止整个事情。然而,主窗口永远不会出现,移除无限循环 - >主窗口出现。
所以我尝试了一种单一的方法,基本的想法是:
connect( highPerformanceTimer, SIGNAL(timer_tick()), this, SLOT(timeOutSlot()) );
connect( this, SIGNAL(graphics_updated()), highPerformanceTimer, SLOT(timer_start()));
因此,计时器滴答,ui(opengl)更新,在更新结束时生成一个信号以重新启动计时器。
只要我不从ui更新代码的末尾删除定时器的重启,我的主窗口就不会显示。
在调试器中,我可以看到代码看起来像它应该工作,它从计时器跳到ui并返回。没有断点,将导致突然的分段错误。
我会感谢任何可能存在问题的提示,或者是否有更好的方法在Qt中实现这一点。
编辑:更多代码
highperformancetimer.h
#ifndef HIGHPERFORMANCETIMER_H
#define HIGHPERFORMANCETIMER_H
#include <QObject>
#include <windows.h>
class HighPerformanceTimer : public QObject
{
Q_OBJECT
public:
HighPerformanceTimer();
signals:
void timer_tick();
public slots:
void timer_start();
private:
// some variables
LARGE_INTEGER highPerformanceCounterValue, highPerformanceCounterFrequency, highPerformanceCounterValueOld;
int interval;
float value;
float last_tick_value;
};
#endif // HIGHPERFORMANCETIMER_H
highperformancetimer.cpp
#include "highperformancetimer.h"
#include "windows.h"
#include "QThread"
HighPerformanceTimer::HighPerformanceTimer()
{
QueryPerformanceFrequency(&highPerformanceCounterFrequency);
}
void HighPerformanceTimer::timer_start(){
float i = 0;
// just burn some time
while( i<1000000 ) i++;
emit HighPerformanceTimer::timer_tick();
}
主OpenGl Widget中的一些代码:
HighPerformanceTimer *highPerformanceTimer;
protected slots:
virtual void timeOutSlot();
NeHeChapter5( QWidget *parent=0, char *name=0 ) : NeHeWidget( 50, parent, name )
{
highPerformanceTimer = new HighPerformanceTimer();
connect( highPerformanceTimer, SIGNAL(timer_tick()), this, SLOT(timeOutSlot()) );
connect( this, SIGNAL(graphics_updated()), highPerformanceTimer, SLOT(timer_start()));
highPerformanceTimer->moveToThread(&timerThread);
highPerformanceTimer->timer_start();
}
void NeHeChapter5::timeOutSlot(){
timeOut();
}
void NeHeChapter5::timeOut()
{
updateGL();
}
void NeHeChapter5::paintGL()
{
//opengl code *snip*
emit graphics_updated();
}
答案 0 :(得分:1)
错误在这里:
NeHeChapter5( QWidget *parent=0, char *name=0 ) : NeHeWidget( 50, parent, name )
{
highPerformanceTimer = new HighPerformanceTimer();
connect( highPerformanceTimer, SIGNAL(timer_tick()), this, SLOT(timeOutSlot()) );
connect( this, SIGNAL(graphics_updated()), highPerformanceTimer, SLOT(timer_start()));
highPerformanceTimer->moveToThread(&timerThread);
highPerformanceTimer->timer_start();
}
你调用timer_start();它在调用者线程中调用,而不是在timerThread
中调用。你甚至没有开始你的线程。首先致电timerThread.start()
。要在线程中调用timer_start(),您需要调用
QMetaObject::invokeMethod(highPerformanceTimer, "timer_start", Qt::QueuedConnection);
它将在新启动的线程中调用timer_start,而不是在调用者线程中调用。
此外,您无需使用完全限定名称调用timer_tick emit HighPerformanceTimer::timer_tick();
可以替换为emit timer_tick();