Qt - 使用由按钮控制的线程的简单示例
Qt - Simple example using threads controlled by push buttons
我一直在尝试让这个简单的示例使用由按钮激活的线程来工作。它基于以下问题的解决方案:
How to implement frequent start/stop of a thread (QThread)
上面的示例解决方案和我下面的代码之间的主要区别是:
- 我使用了 QWidget 而不是 MainWindow
- 为了清楚起见,我更改了信号的名称
- 我的代码包含调试信息
- 我尝试消除 worker 创建的信号,因为它们似乎什么也没做
看来 start/stop 信号没有触发它们相应的插槽,但我没有足够的经验来解决原因。
此外,我不确定信号的用途:
SignalToObj_mainThreadGUI()
那只是可以使用而不能使用的东西吗?
一段时间以来,我一直在尝试让这段代码正常工作,因此非常感谢您的帮助。
main.cpp
#include "threadtest.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ThreadTest w;
w.show();
return a.exec();
}
threadtest.h
#include <QWidget>
#include <QThread>
#include "worker.h"
namespace Ui
{
class ThreadTest;
}
class ThreadTest : public QWidget
{
Q_OBJECT
public:
explicit ThreadTest(QWidget *parent = 0);
~ThreadTest();
signals:
void startWorkSignal();
void stopWorkSignal();
private slots:
void on_startButton_clicked();
void on_stopButton_clicked();
private:
Ui::ThreadTest *ui;
worker *myWorker;
QThread *WorkerThread;
};
threadtest.cpp
#include "threadtest.h"
#include "ui_threadtest.h"
ThreadTest::ThreadTest(QWidget *parent) :
QWidget(parent),
ui(new Ui::ThreadTest)
{
ui->setupUi(this);
myWorker = new worker;
WorkerThread = new QThread;
myWorker->moveToThread(WorkerThread);
connect(this,
SIGNAL(startWorkSignal()),
myWorker,
SLOT(StartWork())
);
connect(this,
SIGNAL(stopWorkSignal()),
myWorker,
SLOT(StopWork())
);
//Debug
this->dumpObjectInfo();
myWorker->dumpObjectInfo();
}
ThreadTest::~ThreadTest()
{
delete ui;
}
void ThreadTest::on_startButton_clicked()
{
qDebug() << "startwork signal emmitted";
emit startWorkSignal();
}
void ThreadTest::on_stopButton_clicked()
{
qDebug() << "stopwork signal emmitted";
emit stopWorkSignal();
}
worker.h
#include <QObject>
#include <QDebug>
class worker : public QObject {
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
~worker();
signals:
void SignalToObj_mainThreadGUI();
//void running();
//void stopped();
public slots:
void StopWork();
void StartWork();
private slots:
void do_Work();
private:
volatile bool running, stopped;
};
worker.cpp
#include "worker.h"
worker::worker(QObject *parent) : QObject(parent), stopped(false),
running(false)
{
qDebug() << "running: " << running;
qDebug() << "stopped: " << stopped;
}
worker::~worker() {}
void worker::do_Work()
{
qDebug() << "inside do Work";
emit SignalToObj_mainThreadGUI();
if (!running || stopped) return;
// actual work here
/*
for (int i = 0; i < 100; i++)
{
qDebug() << "count: " + i;
}
*/
QMetaObject::invokeMethod(this, "do_Work", Qt::QueuedConnection);
}
void worker::StopWork()
{
qDebug() << "inside StopWork";
stopped = true;
running = false;
//emit stopped();
}
void worker::StartWork()
{
qDebug() << "inside StartWork";
stopped = false;
running = true;
//emit running();
do_Work();
}
插槽未被触发,因为您已将 myWork 移动到线程 WorkerThread,但没有 运行 该线程中的事件循环。在 threadtest.cpp 中,添加
WorkerThread .start();
之后
myWorker = new worker;
WorkerThread = new QThread;
myWorker->moveToThread(WorkerThread);
你应该写
WorkerThread->start();
或者您可以使用 ThreadTest 对象的线程代替 WorkerThread(在这种情况下不需要 WorkerThread):
myWorker->moveToThread(thread()); // this->thread
我一直在尝试让这个简单的示例使用由按钮激活的线程来工作。它基于以下问题的解决方案:
How to implement frequent start/stop of a thread (QThread)
上面的示例解决方案和我下面的代码之间的主要区别是:
- 我使用了 QWidget 而不是 MainWindow
- 为了清楚起见,我更改了信号的名称
- 我的代码包含调试信息
- 我尝试消除 worker 创建的信号,因为它们似乎什么也没做
看来 start/stop 信号没有触发它们相应的插槽,但我没有足够的经验来解决原因。
此外,我不确定信号的用途:
SignalToObj_mainThreadGUI()
那只是可以使用而不能使用的东西吗?
一段时间以来,我一直在尝试让这段代码正常工作,因此非常感谢您的帮助。
main.cpp
#include "threadtest.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); ThreadTest w; w.show(); return a.exec(); }
threadtest.h
#include <QWidget> #include <QThread> #include "worker.h" namespace Ui { class ThreadTest; } class ThreadTest : public QWidget { Q_OBJECT public: explicit ThreadTest(QWidget *parent = 0); ~ThreadTest(); signals: void startWorkSignal(); void stopWorkSignal(); private slots: void on_startButton_clicked(); void on_stopButton_clicked(); private: Ui::ThreadTest *ui; worker *myWorker; QThread *WorkerThread; };
threadtest.cpp
#include "threadtest.h" #include "ui_threadtest.h" ThreadTest::ThreadTest(QWidget *parent) : QWidget(parent), ui(new Ui::ThreadTest) { ui->setupUi(this); myWorker = new worker; WorkerThread = new QThread; myWorker->moveToThread(WorkerThread); connect(this, SIGNAL(startWorkSignal()), myWorker, SLOT(StartWork()) ); connect(this, SIGNAL(stopWorkSignal()), myWorker, SLOT(StopWork()) ); //Debug this->dumpObjectInfo(); myWorker->dumpObjectInfo(); } ThreadTest::~ThreadTest() { delete ui; } void ThreadTest::on_startButton_clicked() { qDebug() << "startwork signal emmitted"; emit startWorkSignal(); } void ThreadTest::on_stopButton_clicked() { qDebug() << "stopwork signal emmitted"; emit stopWorkSignal(); }
worker.h
#include <QObject> #include <QDebug> class worker : public QObject { Q_OBJECT public: explicit worker(QObject *parent = 0); ~worker(); signals: void SignalToObj_mainThreadGUI(); //void running(); //void stopped(); public slots: void StopWork(); void StartWork(); private slots: void do_Work(); private: volatile bool running, stopped; };
worker.cpp
#include "worker.h" worker::worker(QObject *parent) : QObject(parent), stopped(false), running(false) { qDebug() << "running: " << running; qDebug() << "stopped: " << stopped; } worker::~worker() {} void worker::do_Work() { qDebug() << "inside do Work"; emit SignalToObj_mainThreadGUI(); if (!running || stopped) return; // actual work here /* for (int i = 0; i < 100; i++) { qDebug() << "count: " + i; } */ QMetaObject::invokeMethod(this, "do_Work", Qt::QueuedConnection); } void worker::StopWork() { qDebug() << "inside StopWork"; stopped = true; running = false; //emit stopped(); } void worker::StartWork() { qDebug() << "inside StartWork"; stopped = false; running = true; //emit running(); do_Work(); }
插槽未被触发,因为您已将 myWork 移动到线程 WorkerThread,但没有 运行 该线程中的事件循环。在 threadtest.cpp 中,添加
WorkerThread .start();
之后
myWorker = new worker;
WorkerThread = new QThread;
myWorker->moveToThread(WorkerThread);
你应该写
WorkerThread->start();
或者您可以使用 ThreadTest 对象的线程代替 WorkerThread(在这种情况下不需要 WorkerThread):
myWorker->moveToThread(thread()); // this->thread