Реализуйте точный таймер в Qt

Так как мне нужен более точный таймер, чем Qt с разрешением ~ 15 мс, я попытался реализовать свой собственный таймер, используя QueryPerformanceCounter () из windows api.

Моим первым шагом было наследование от QObject и создание таймера с бесконечным циклом, который генерирует сигнал каждую секунду. Я попытался переместить этот таймер в свой собственный поток с помощью moveToThread (), чтобы он просто обновлял мое главное окно каждую секунду, а не блокировал все это. Однако главное окно никогда не появится, удалив бесконечный цикл -> появится главное окно.

Итак, я попробовал подход одиночного выстрела, основная идея:

 connect( highPerformanceTimer, SIGNAL(timer_tick()), this, SLOT(timeOutSlot()) );
connect( this,  SIGNAL(graphics_updated()), highPerformanceTimer, SLOT(timer_start()));

Таким образом, таймеры тика, пользовательский интерфейс (opengl) обновляется, в конце обновления генерируется сигнал для перезапуска таймера.

Тем не менее мое главное окно не будет отображаться, пока я не удаляю перезапуск таймера с конца кода обновления пользовательского интерфейса.

В отладчике я вижу, что код работает должным образом, он переходит от таймера к пользовательскому интерфейсу и обратно. Без точек останова это приведет к внезапной ошибке сегментации.

Я был бы благодарен за любую подсказку, где может быть проблема или если есть лучший способ реализовать это в 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:

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

3

Решение

Ошибка здесь:

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

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector