自定义类,具有自己的QTimer和QThread

custom class with its own QTimer and QThread

本文关键字:QTimer QThread 自己的 自定义      更新时间:2023-10-16

我想为机器人的传感器的一些项目创建一个具有自己的QTimer和QThread的类。经过一番搜索,这就是我找到的

#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QObject>
#include <QDebug>

//#####################( Robot Class  )#########################3
class Robot : public QObject
{
public:
    Robot(QObject *parent = 0);
    ~Robot();
private:
    QTimer  *mQTimer;
    QThread *mQThread;
public slots:
    void update();
};
Robot::Robot(QObject *parent)
    : QObject(parent)
{
     mQTimer = new QTimer(0);
    mQThread = new QThread(this);
    mQTimer->setInterval(1);
    mQTimer->moveToThread(mQThread);
    connect(mQTimer, SIGNAL(timeout()), this, SLOT(update()));
    connect(mQThread, SIGNAL(started()), mQTimer, SLOT(start()));
   mQThread->start();
   //mQTimer->start();
}
Robot::~Robot()
{
    delete mQTimer;
    delete mQThread;
}
void Robot::update()
{
    qDebug() << "Robot is updating ...";
}
//##################( Main )###########################
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Robot *myRobot = new Robot(0);
    return a.exec();
}

我得到这个错误

QObject::connect: No such slot QObject::update() in ..untitled1main.cpp:34
QObject::connect: No such slot QObject::update() in ..untitled1main.cpp:34

您在类中缺少Q_OBJECT宏,也尽量避免这样命名方法,因为您可以将其与Qt方法名称混合。还要为您创建的每个类创建额外的头文件和cpp文件,在本例中创建robot. h和robot.cpp.

class Robot : public QObject
{
Q_OBJECT
public:
    Robot(QObject *parent = 0);
    ~Robot();
...

以下内容适用于我。您忘记使用Q_OBJECT宏并包含为Robot定义静态元数据的moc输出。

这段代码当然没有意义,因为Robot::update槽将在主线程中执行。

您的代码有两个线程:主线程(Robot对象所在的地方)和robot.mThread(计时器所在的地方)。计时器将在mThread中超时,并将在主线程上排队进行插槽调用。这个槽位调用最终将调用robot.update,而a.exec在堆栈上。

注意,不需要显式地使用new在堆上分配计时器和线程。它们应该是Robot或其PIMPL的直接成员。

main.cpp

#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QDebug>
class Robot : public QObject
{
   Q_OBJECT
   QTimer mTimer;
   QThread mThread;
public:
   Robot(QObject *parent = 0) : QObject(parent) {
      connect(&mTimer, &QTimer::timeout, this, &Robot::update);;
      mTimer.start(1000);
      mTimer.moveToThread(&mThread);
      mThread.start();
   }
   Q_SLOT void update() {
      qDebug() << "updating";
   }
};
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   Robot robot;
   return a.exec();
}
#include "main.moc"

将整个机器人移动到自己的线程中会更有意义。注意,当您这样做时,您需要在robot拥有的所有对象上设置父级,以便它们都与Robot对象一起切换线程。

Thread类修复了QThread长期存在的可用性错误——它把它变成了一个真正的RAII类,可以在任何时候安全地销毁。

main.cpp

#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QDebug>
class Thread : public QThread {
   using QThread::run;
public:
   ~Thread() { quit(); wait(); }
};
class Robot : public QObject
{
   Q_OBJECT
   QTimer mTimer;
   int mCounter;
public:
   Robot(QObject *parent = 0) : QObject(parent), mTimer(this), mCounter(0) {
      connect(&mTimer, &QTimer::timeout, this, &Robot::update);;
      mTimer.start(1000);
   }
   Q_SLOT void update() {
      qDebug() << "updating";
      if (++mCounter > 5) qApp->exit();
   }
};
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   Robot robot;
   Thread thread;
   robot.moveToThread(&thread);
   thread.start();
   return a.exec();
}
#include "main.moc"