说明:
传统的图形界面应用程序都只有一个线程执行,并且一次执行一个操作。如果用户调用一个比较耗时的操作,就会冻结界面响应。
一个解决方法是按照事件处理的思路:
调用 Void QApplication::processEvents() 或 void QApplication::processEvents ( int maxtime ) 来强迫事件循环进行,但是这种做法是有潜在风险的。
QThread thread;
Object obj;
Dummy dummy;
obj.moveToThread(&thread);
QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(slot()));
thread.start();
(1)thread.h:
#ifndef THREAD_H
#define THREAD_H
#include
class Thread : public QThread
{
Q_OBJECT
public:
Thread();
void setMessage(const QString &message);
void stop();
protected:
void run();
private:
QString messageStr;
volatile bool stopped;
};
#endif
(2)threaddialog.h:
#ifndef THREADDIALOG_H
#define THREADDIALOG_H
#include
#include "thread.h"
class QPushButton;
class ThreadDialog : public QDialog
{
Q_OBJECT
public:
ThreadDialog(QWidget *parent = 0);
protected:
void closeEvent(QCloseEvent *event);
private slots:
void startOrStopThreadA();
void startOrStopThreadB();
private:
Thread threadA;
Thread threadB;
QPushButton *threadAButton;
QPushButton *threadBButton;
QPushButton *quitButton;
};
#endif
(3)thread.cpp
#include
#include
#include "thread.h"
Thread::Thread()
{
stopped = false;
}
void Thread::setMessage(const QString &message)
{
messageStr = message;
}
void Thread::run()
{
while (!stopped)
std::cerr << qPrintable(messageStr);
stopped = false;
std::cerr << std::endl;
}
void Thread::stop()
{
stopped = true;
}
(4)threaddialog.cpp
#include
#include "threaddialog.h"
ThreadDialog::ThreadDialog(QWidget *parent)
: QDialog(parent)
{
threadA.setMessage("A");
threadB.setMessage("B");
threadAButton = new QPushButton(tr("Start A"));
threadBButton = new QPushButton(tr("Start B"));
quitButton = new QPushButton(tr("Quit"));
quitButton->setDefault(true);
connect(threadAButton, SIGNAL(clicked()),
this, SLOT(startOrStopThreadA()));
connect(threadBButton, SIGNAL(clicked()),
this, SLOT(startOrStopThreadB()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(threadAButton);
mainLayout->addWidget(threadBButton);
mainLayout->addWidget(quitButton);
setLayout(mainLayout);
setWindowTitle(tr("Threads"));
}
void ThreadDialog::startOrStopThreadA()
{
if (threadA.isRunning()) {
threadA.stop();
threadAButton->setText(tr("Start A"));
} else {
threadA.start();
threadAButton->setText(tr("Stop A"));
}
}
void ThreadDialog::startOrStopThreadB()
{
if (threadB.isRunning()) {
threadB.stop();
threadBButton->setText(tr("Start B"));
} else {
threadB.start();
threadBButton->setText(tr("Stop B"));
}
}
void ThreadDialog::closeEvent(QCloseEvent *event)
{
threadA.stop();
threadB.stop();
threadA.wait();
threadB.wait();
event->accept();
}
(5)main()
#include
#include "threaddialog.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ThreadDialog dialog;
dialog.show();
return app.exec();
}
#include
#include
#include
#include
class Dummy:public QObject
{
Q_OBJECT
public:
Dummy(QObject* parent=0):QObject(parent) {}
public slots:
void emitsig()
{
emit sig();
}
signals:
void sig();
};
class Object:public QObject
{
Q_OBJECT
public:
Object(){}
public slots:
void slot()
{
qDebug()<<"from thread slot:" <
结果:slot确实不在主线程中运行(这么简单不值得欢呼么?)
main thread: 0x1a5c