I am trying to learn Qt and I am attempting to do so by making a little titres game. Currently I have a 2d array which represents the game board.
Every second this 2d array is changed by a thread (representing the passage of time) and then this thread emits a signal telling the main GUI to update based on the new game board.
My Thread is as follows:
gamethread.h
#ifndef GAMETHREAD_H
#define GAMETHREAD_H
#include <QtCore>
#include <QThread>
#include<QMetaType>
class GameThread : public QThread
{
Q_OBJECT
public:
explicit GameThread(QObject *parent = 0);
void run();
private:
int board[20][10]; //[width][height]
void reset();
signals:
void TimeStep(int board[20][10]);
};
#endif // GAMETHREAD_H
gamethread.cpp
#include "gamethread.h"
#include <QtCore>
#include <QtDebug>
//Game Managment
GameThread::GameThread(QObject *parent) :
QThread(parent)
{
reset();
}
void GameThread::reset()
{
...
}
//Running The Game
void GameThread::run()
{
//Do Some Stuff
emit TimeStep(board);
}
and the main UI which should receive the signal and update based on the new board is:
tetris.h
#ifndef TETRIS_H
#define TETRIS_H
#include <QMainWindow>
#include "gamethread.h"
namespace Ui{
class Tetris;
}
class Tetris : public QMainWindow
{
Q_OBJECT
public:
explicit Tetris(QWidget *parent = 0);
~Tetris();
GameThread *mainThread;
private:
Ui::Tetris *ui;
private slots:
int on_action_Quit_activated();
void on_action_NewGame_triggered();
public slots:
void onTimeStep(int board[20][10]);
};
#endif // TETRIS_H
tetris.cpp
#include <QMessageBox>
#include <QtGui>
#include <boost/lexical_cast.hpp>
#include <string>
#include "tetris.h"
#include "ui_tetris.h"
Tetris::Tetris(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Tetris)
{
ui->setupUi(this);
mainThread = new GameThread(this);
connect(mainThread, SIGNAL(TimeStep(int[20][10])),
this, SLOT(onTimeStep(int[20][10])),
Qt::QueuedConnection);
}
Tetris::~Tetris()
{
delete ui;
}
void Tetris::onTimeStep(int board[20][10])
{
//receive new board update my display
}
void Tetris::on_action_NewGame_triggered()
{
mainThread->start();
}
When I run this I get:
QObject::connect: Cannot queue arguments of type ‘int[20][10]’
(Make sure ‘int[20][10]’ is registered using qRegisterMetaType().)
I have looked into qRegisterMetaType and Q_DECLARE_METATYPE but I am not even remotely sure how to use them or even if I must use them. Can someone give the QT newbie some assistance?
You can wrap the board data in a class. It won’t work if you merely typedef’d it, since Qt will try to use non-array operator new to create instances of board data. The compiler will detect it and rightfully complain.
It’s bad style to derive from QThread like you are doing and use it as a generic QObject. QThread is conceptually a thread controller, not a thread itself. See this answer for the idiomatic way to do it. Your GameThread should be a QObject, not a QThread.
So: