QT - 强制对象处理传入信号
QT - force an object to process incoming signals
我想知道如何告诉 QObject 处理所有信号并调用与它们关联的槽。这是我遇到的具体问题,以便更好地描述问题:
我的程序由三个 Qthread 组成:Main、Communication 和 Input。
通信线程通过网络处理通信,输入线程处理用户输入,两者都有几个到主线程的信号槽连接。每当网络事件发生时,或者每当用户输入命令行命令时,都会调用来自相应线程的信号,然后激活主线程中适当的连接插槽。主线程的作用就是处理这些事件。我的代码如下所示:
QApplication a(argc, argv);
CommObj co; //inherits from QThread
co.start(); //Starts the thread
InputObj io; //inherits from QThread
io.start(); //Starts the thread
MainObj u(&co,&io);
return a.exec();
现在,我要实现的是主线程不执行到最后一行。
我的意图是在 MainObj 的构造函数中调用一个方法 运行() ,它将按照以下方式做一些事情:
void run ()
{
forever
{
//process all signals..
}
}
但是,我不知道如何实现所有信号部分的处理。非常欢迎任何有关如何完成此操作的建议(包括解决方法)。
你需要的是processEvents
功能。例如,如果您不希望用户能够与小部件交互,但希望图形更新,请使用
processEvents(QEventLoop::ExcludeUserInputEvents);
详情见documentation。
这完全没有必要。 a.exec()
运行是一个事件循环,它将接收和处理其他线程发送的事件。
当由于在不同线程中发出信号而调用槽时,Qt 将 QMetaCallEvent
发送到接收器对象。 QObject::event
方法可以根据事件中的数据重新合成slot调用
因此,您什么都不用做。 a.exec()
为所欲为。随意从 MainObj
的构造函数中调用它,如 qApp->exec()
或 QEventLoop loop; loop.exec()
,但这是相当糟糕的设计。
真题是:
为什么需要 MainObj
的构造函数来旋转事件循环?
您在 io
处理哪种 "user input"?您无法从该线程访问任何 GUI 对象。
如果您使用 Qt 的网络,为什么要从 QThread
派生?您绝对不想这样做 - 除非您旋转事件循环,否则它不会起作用,因此您最好使用 QThread
而不做任何更改。好吧,为了安全起见,您只需要使线程可破坏,所以:
class Thread {
using QThread::run; // make it final
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { requestInterruption(); quit(); wait(); }
};
无论如何,通过不使用旋转事件循环的标准 QThread
,通信将是一种方式。此类线程中的任何内容都无法对来自其他线程的信号做出反应。
您需要重构如下:
如上使用Thread
class。随时被破坏是安全的
具有 运行 异步使用 signals/slots/timers 的工作对象。
将构造的 worker 移动到它们的线程。
我想知道如何告诉 QObject 处理所有信号并调用与它们关联的槽。这是我遇到的具体问题,以便更好地描述问题:
我的程序由三个 Qthread 组成:Main、Communication 和 Input。
通信线程通过网络处理通信,输入线程处理用户输入,两者都有几个到主线程的信号槽连接。每当网络事件发生时,或者每当用户输入命令行命令时,都会调用来自相应线程的信号,然后激活主线程中适当的连接插槽。主线程的作用就是处理这些事件。我的代码如下所示:
QApplication a(argc, argv);
CommObj co; //inherits from QThread
co.start(); //Starts the thread
InputObj io; //inherits from QThread
io.start(); //Starts the thread
MainObj u(&co,&io);
return a.exec();
现在,我要实现的是主线程不执行到最后一行。 我的意图是在 MainObj 的构造函数中调用一个方法 运行() ,它将按照以下方式做一些事情:
void run ()
{
forever
{
//process all signals..
}
}
但是,我不知道如何实现所有信号部分的处理。非常欢迎任何有关如何完成此操作的建议(包括解决方法)。
你需要的是processEvents
功能。例如,如果您不希望用户能够与小部件交互,但希望图形更新,请使用
processEvents(QEventLoop::ExcludeUserInputEvents);
详情见documentation。
这完全没有必要。 a.exec()
运行是一个事件循环,它将接收和处理其他线程发送的事件。
当由于在不同线程中发出信号而调用槽时,Qt 将 QMetaCallEvent
发送到接收器对象。 QObject::event
方法可以根据事件中的数据重新合成slot调用
因此,您什么都不用做。 a.exec()
为所欲为。随意从 MainObj
的构造函数中调用它,如 qApp->exec()
或 QEventLoop loop; loop.exec()
,但这是相当糟糕的设计。
真题是:
为什么需要
MainObj
的构造函数来旋转事件循环?您在
io
处理哪种 "user input"?您无法从该线程访问任何 GUI 对象。如果您使用 Qt 的网络,为什么要从
QThread
派生?您绝对不想这样做 - 除非您旋转事件循环,否则它不会起作用,因此您最好使用QThread
而不做任何更改。好吧,为了安全起见,您只需要使线程可破坏,所以:class Thread { using QThread::run; // make it final public: Thread(QObject * parent = 0) : QThread(parent) {} ~Thread() { requestInterruption(); quit(); wait(); } };
无论如何,通过不使用旋转事件循环的标准
QThread
,通信将是一种方式。此类线程中的任何内容都无法对来自其他线程的信号做出反应。
您需要重构如下:
如上使用
Thread
class。随时被破坏是安全的具有 运行 异步使用 signals/slots/timers 的工作对象。
将构造的 worker 移动到它们的线程。