不能发出QThread的信号 [英] Can not emit QThread's signals
问题描述
QT 5.1.0rc2,msvc 2010,Microsoft Visual Studio 2010
QT 5.1.0rc2 , msvc 2010 , Microsoft Visual Studio 2010
它是Qt 4.8.4,msvc 2008的工作代码
It is working code on Qt 4.8.4 , msvc 2008
我有编译错误
#if defined( HANDLE_PROCESSING_IN_MAIN_THREAD )
if(QThread::currentThread() != this)
emit started();
#endif
inherited::run();
和
#if defined( HANDLE_PROCESSING_IN_MAIN_THREAD )
if(QThread::currentThread() != this)
emit finished();
#endif
错误C2660:'QThread :: started ':函数不接受0个参数
错误C2660:'QThread :: finished':函数不接受0个参数
error C2660: 'QThread::started' : function does not take 0 arguments
error C2660: 'QThread::finished' : function does not take 0 arguments
$ b b
在QThread中我看到了
In QThread i have seen
Q_SIGNALS:
void started(
#if !defined(Q_QDOC)
QPrivateSignal
#endif
);
void finished(
#if !defined(Q_QDOC)
QPrivateSignal
#endif
);
当我定义Q_QDOC我在QT源中有很多错误。
when I defined Q_QDOC I got many errors in QT sources.
QPrivateSignal是在宏Q_OBJECT中定义的空结构
QPrivateSignal is empty structure that defined in macro Q_OBJECT
需要一个不影响应用程序体系结构的解决方案, .8.4
Need a solution that does not affect the architecture of the application, as to be backward compatible with Qt4.8.4
有些想法?
推荐答案
自动。
您尝试使用预处理器来处理代码的两种变体:在gui线程或专用线程中处理。
You're trying to use preprocessor to handle two variants of the code: processing in the gui thread or a dedicated thread. Qt provides a very easy way of dealing with it.
-
在一个类中实现你的处理功能,派生自
QObject
。你也可以在重新实现的event()
方法中,如果你更容易通过发布事件而不是调用槽来开始处理。
Implement your processing functionality in a slot in a class deriving from
QObject
. You could also do it in the reimplementedevent()
method if it's easier for you to start processing by posting an event rather than invoking a slot.
如果你想让对象的槽在不同的线程中运行,使用 moveToThread()
方法。
If you want your object's slots to run in a different thread, use the moveToThread()
method.
您不需要从 QThread
派生。其默认实现 run()
旋转本地事件循环。
You don't need to derive from QThread
. Its default implementation of run()
spins a local event loop.
与生存在GUI线程中兼容,它必须以小块进行处理并放弃控制,以使GUI不会停顿。
If you want your object to be compatible with living in the GUI thread, it must do its processing in small chunks and relinquish control so that the GUI doesn't stall.
下面是一个完整的示例,演示如何在GUI或单独的线程中启动worker对象,如何在线程之间安全移动它。
Below is a complete example that demonstrates how you can start the worker object in either GUI or a separate thread, and how you can safely move it between threads.
main.cpp
#include <QApplication>
#include <QVBoxLayout>
#include <QPushButton>
#include <QThread>
#include <QBasicTimer>
#include <QElapsedTimer>
#include <QLabel>
#include <QDebug>
class Helper : private QThread {
public:
using QThread::usleep;
};
class Worker : public QObject {
Q_OBJECT
int m_counter;
bool m_busy;
QBasicTimer m_timer;
void timerEvent(QTimerEvent * ev);
public:
Worker(QObject *parent = 0) : QObject(parent), m_busy(false) {}
Q_SLOT void start() {
if (m_busy) return;
m_counter = 0;
m_busy = true;
m_timer.start(0, this);
}
Q_SIGNAL void done();
Q_SIGNAL void progress(int);
// must be called from within the working thread, so we wrap it in a slot
Q_INVOKABLE void moveToThread(QThread *t) { QObject::moveToThread(t); }
};
void Worker::timerEvent(QTimerEvent * ev)
{
const int busyTime = 50; // [ms] - longest amount of time to stay busy
const int testFactor = 128; // number of iterations between time tests
const int maxCounter = 10000;
if (ev->timerId() != m_timer.timerId()) return;
QElapsedTimer t;
t.start();
while (1) {
// do some "work"
Helper::usleep(100);
m_counter ++;
// exit when the work is done
if (m_counter > maxCounter) {
emit progress(100);
emit done();
m_busy = false;
break;
}
// exit when we're done with a timed "chunk" of work
// Note: QElapsedTimer::elapsed() may be expensive, so we call it once every testFactor iterations
if ((m_counter % testFactor) == 1 && t.elapsed() > busyTime) {
emit progress(m_counter*100/maxCounter);
break;
}
}
}
class Window : public QWidget {
Q_OBJECT
QLabel *m_label;
QThread *m_thread;
QObject *m_worker;
Q_SIGNAL void start();
Q_SLOT void showProgress(int p) { m_label->setText(QString("%1 %").arg(p)); }
void moveWorkerToThread(QThread *thread) {
qDebug() << QMetaObject::invokeMethod(m_worker, "moveToThread", Q_ARG(QThread*, thread));
}
Q_SLOT void on_startGUI_clicked() {
moveWorkerToThread(qApp->thread());
emit start();
}
Q_SLOT void on_startWorker_clicked() {
moveWorkerToThread(m_thread);
emit start();
}
public:
Window(QWidget *parent = 0, Qt::WindowFlags f = 0) :
QWidget(parent, f), m_label(new QLabel), m_thread(new QThread(this)), m_worker(new Worker)
{
QVBoxLayout * l = new QVBoxLayout(this);
QPushButton * btn;
btn = new QPushButton("Start in GUI Thread");
btn->setObjectName("startGUI");
l->addWidget(btn);
btn = new QPushButton("Start in Worker Thread");
btn->setObjectName("startWorker");
l->addWidget(btn);
l->addWidget(m_label);
connect(m_worker, SIGNAL(progress(int)), SLOT(showProgress(int)));
m_worker->connect(this, SIGNAL(start()), SLOT(start()));
m_thread->start();
QMetaObject::connectSlotsByName(this);
}
~Window() {
m_thread->quit();
m_thread->wait();
delete m_worker;
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qRegisterMetaType<QThread*>("QThread*"); // for invokeMethod to work
Window w;
w.show();
return a.exec();
}
#include "main.moc"
这篇关于不能发出QThread的信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!