说明:
传统的图形界面应用程序都只有一个线程执行,并且一次执行一个操作。如果用户调用一个比较耗时的操作,就会冻结界面响应。
一个解决方法是按照事件处理的思路:
调用 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 <QThread> 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 <QDialog> #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 <QtCore> #include <iostream> #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 <QtGui> #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 <QApplication> #include "threaddialog.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); ThreadDialog dialog; dialog.show(); return app.exec(); }
#include <QtCore/QCoreApplication> #include <QtCore/QObject> #include <QtCore/QThread> #include <QtCore/QDebug> 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:" <<QThread::currentThreadId(); } }; #include "main.moc" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug()<<"main thread:"<<QThread::currentThreadId(); QThread thread; Object obj; Dummy dummy; obj.moveToThread(&thread); QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(slot())); thread.start(); dummy.emitsig(); return a.exec(); }
结果:slot确实不在主线程中运行(这么简单不值得欢呼么?)
main thread: 0x1a5c