Reputation: 808
This question seems to have been answered in one form or another when someone is overloading a thread with their own class, but what about just trying to use the QTimer class without extending the QThread class. I am attempting to use the QTimer for QT. Their simple example on
http://qt-project.org/doc/qt-4.7/qtimer.html
Their example is as follows:
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
But when I attempt this, I keep on getting the error:
QObject::startTimer: Timers can only be used with threads started with QThread.
I am working through the set of videos by Jamie King on YouTube through his Game Engine Development series. I plan on folllowing his videos to the tee, so any abstract completely different coding techniques is not preferred at this moment. This is what I have so far.
I tried to make a small quick side project to keep the code as simple as I could. I do not have any build errors - they only occur after the program starts to
QTimerApp.cpp
#include <QtWidgets\qapplication.h>
#include <QtWidgets\qwidget.h>
#include "GLWin.h"
int main(int argc, char* argv[])
{
QApplication application(argc, argv);
GLWin MyGL;
MyGL.show();
return application.exec();
}
GLWin.h
#ifndef My_GL_Window
#define My_GL_Window
#include <QtOpenGL\qglwidget>
#include <QtCore\qtimer.h>
class GLWin : public QGLWidget
{
Q_OBJECT // preprocessor from QT - gives what we need for slots
// Declaration* - should be in class. Declared in class, but not defined.
// Needs to be defined in .cpp (manually)
// Or allow QT to define for us. (preferred)
// use moc.exe (found in $(ProjectDir)..\Middleware\Qt\bin\moc.exe against myGLWindow.h
// C:\MyEngine\ProgramFiles\Middleware\Qt\bin\moc.exe myGLWindow.h > MyGLWindow_moc.cpp
// then include MyGLWindow_moc.cpp in project
GLuint vertexBufferID;
QTimer myTimer;
protected:
void initializeGL();
void paintGL();
private slots: //All classes that contain signals or slots must mention Q_OBJECT at the top of their declaration.
// They must also derive (directly or indirectly) from QObject.
private:
void updateWin();
};
#endif
GLWin.cpp
#include <gl\glew.h>
#include "GLWin.h"
#include <cassert>
#include <QTCore\QTimer.h>
void GLWin::initializeGL()
{
GLenum errorCode = glewInit();
assert(errorCode == 0);
glGenBuffers(1, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
float verts[] =
{
+0.0f, +0.1f,
-0.1f, -0.1f,
+0.1f, -0.1f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
QTimer* timer = new QTimer(0);
connect(timer, SIGNAL(timeout()), this, SLOT(updateWin()));
timer->start();
}
void GLWin::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void GLWin::updateWin()
{
}
Most of the research that I have come up with has to do with overloading the run() function when their class has extended QThread. As far as I can tell, I shouldn't have to extend nor create another class for a simple timer loop to occur. Having extended QWidget already, my object is already a QObject type.
Any assistance is truly appreciated. Thank you!
Upvotes: 2
Views: 437
Reputation: 808
Wow. Silly me, I finally found the answer after too long.
... while in debugging mode, make sure all of your .lib and .dll that you are linking are the debugger and NOT the release .dll.
... ie, I was using
Qt5OpenGL.dll and Qt5OpenGL.lib
instead of Qt5OpenGLd.dll and Qt5OpenGLd.lib
... I feel a fool but this will never catch me again. Just blindly choosing "Oh hey.. I see Qt5Open...." Good enough! Just make sure that you check all of your files and not just those two.
/facepalm!
Upvotes: -2
Reputation: 53145
Your code has many issues:
QtFoo\
style include. You better use forward slashes as that is the common way of using it for good.
You do not actually need to use QtFoo
explicitly and it is also better as it makes the buildsystem more reliable and the project more portable.
You do not use Q_DECL_FINAL
optimization for your end class.
You do not use Q_DECL_OVERRIDE
for overridden member methods.
You do not actually mark your slot as slot.
You do not set a parent for your timer, so it leaks memory.
You use cassert
when Qt has its own Q_ASSERT
and Q_ASSERT_X
.
You use qfoo.h
style include, whereas QFoo
is the common usage pattern.
You do not utilize the new signal-slot syntax.
This is the working version for me:
#include <glew.h>
#include <QApplication>
#include <QGLWidget>
#include <QTimer>
class GLWin Q_DECL_FINAL : public QGLWidget
{
Q_OBJECT
GLuint vertexBufferID;
QTimer myTimer;
protected:
void initializeGL() Q_DECL_OVERRIDE
{
GLenum errorCode = glewInit();
Q_ASSERT(errorCode == 0);
glGenBuffers(1, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
float verts[] =
{
0.0f, 0.1f,
-0.1f, -0.1f,
0.1f, -0.1f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &GLWin::updateWin);
timer->start();
}
void paintGL() Q_DECL_OVERRIDE
{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
private slots:
void updateWin() {}
};
#include "main.moc"
int main(int argc, char **argv)
{
QApplication application(argc, argv);
GLWin MyGL;
MyGL.show();
return application.exec();
}
TEMPLATE = app
TARGET = main
QT += widgets opengl
SOURCES += main.cpp
packagesExist(glew) {
CONFIG += link_pkgconfig
PKGCONFIG += glew
}
qmake && make && ./main
Upvotes: 3