3

由于我需要一个比 Qt 更精确的计时器,其分辨率约为 15 毫秒,因此我尝试使用 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 中实现这一点,我将不胜感激。

编辑:更多代码

高性能定时器.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

高性能定时器.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 小部件的一些代码:

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();
}
4

1 回答 1

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_tickemit HighPerformanceTimer::timer_tick();可以替换为emit timer_tick();

于 2012-09-05T17:19:41.450 回答