因此,机制是您不能在线程内部修改小部件,否则应用程序将崩溃并显示错误,例如:
QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
Segmentation fault
为了解决这个问题,您需要将线程工作封装在一个类中,例如:
class RunThread:public QThread{
Q_OBJECT
public:
void run();
signals:
void resultReady(QString Input);
};
run() 函数包含您想要执行的所有工作。
在您的父类中,您将拥有一个调用函数来生成数据和一个 QT 窗口小部件更新函数:
class DevTab:public QWidget{
public:
void ThreadedRunCommand();
void DisplayData(QString Input);
...
}
然后,要调用线程,您需要连接一些插槽,这些插槽...
void DevTab::ThreadedRunCommand(){
RunThread *workerThread = new RunThread();
connect(workerThread, &RunThread::resultReady, this, &DevTab::UpdateScreen);
connect(workerThread, &RunThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
连接函数有4个参数,第1个参数是原因类,第2个参数是该类中的信号。参数3是回调函数的类,参数4是类内的回调函数。
然后您可以在子线程中编写一个函数来生成数据:
void RunThread::run(){
QString Output="Hello world";
while(1){
emit resultReady(Output);
sleep(5);
}
}
然后你的父函数中会有一个回调函数来更新小部件:
void DevTab::UpdateScreen(QString Input){
DevTab::OutputLogs->append(Input);
}
然后,当你运行它时,父级中的小部件将在每次线程中调用emit宏时更新。如果连接函数被正确配置,它将自动获取发出的参数,并将其存储到回调函数的输入参数中。
工作原理如下:
1. 我们初始化该类。
2. 我们设置处理线程完成后会发生什么以及如何处理“返回”的数据(也称为发出数据),因为我们无法以通常的方式从线程中返回数据。
3. 然后我们使用调用`->start()`(这是硬编码到QThread中的)来运行线程,并且QT会查找类中硬编码的名称`.run()`成员函数。
4. 每次在子线程中调用`emit resultReady`宏时,它都会将QString数据存储到一些共享数据区域中,该区域被卡在线程之间的某个地方。
5. QT检测到resultReady已触发,并向您的函数UpdateScreen(QString)发出信号,以接受从run()发出的QString作为父线程中的实际函数参数。
6. 这将在每次触发emit关键字时重复发生。
基本上,
connect()
函数是子线程和父线程之间的接口,以便数据可以来回传输。
注意:resultReady()不需要定义。将其视为QT内部存在的宏即可。
workerThread->start()
而不是使用workerThread->run()
启动线程吗? - NIA