当前位置:网站首页>QT中线程调用GUI主线程控件的问题
QT中线程调用GUI主线程控件的问题
2022-08-03 08:09:00 【天天进步2015】
之前写过一篇文章,是传界面指针到线程中去,从而在线程中操作主界面中控件。
今天发现,这种方法是极其错误的,文章我已经删掉,希望没有误人子弟。
前面转的两篇文章中对于为什么不能在线程中操纵界面控件指针有了很好的解释。下面在做下解释:
尽管QObject是可重入的,但GUI类,特别是QWidget与它的所有子类都是不可重入的。它们仅用于主线程。正如前面提到过 的,QCoreApplication:: exec() 也必须从那个线程中被调用。实践上,不会在别的线程中使用GUI类,它们工作在主线程上,把一些耗时的操作放入独立的工作线程中,当工作线程运行完成,把 结果在主线程所拥有的屏幕上显示。
下面的几个帖子是我在解决问题的过程中看到的几个很有帮助的帖子,一并贴下:
http://www.qtcn.org/bbs/read.php?tid=12121&keyword=%CF%DF%B3%CC
http://www.qtcn.org/bbs/read.php?tid=13508&keyword=%CF%DF%B3%CC
http://www.qtcn.org/bbs/read.php?tid=18586&keyword=%CF%DF%B3%CC
下面截取里面比较有价值的回复:
线程里面直接操作界面元素是肯定不行的,即使不总是出现错误,偶尔也会出莫明其妙,在 文档里面已经有说了,你再找找看,
你需要使用比如postEvent之类的异步处理方式.
至于进程中的那个错误,你设断点调试下吧.
不可以在非界面的进程中直接操作界面的
Qt的文档有这么说
据说4之前版本可以,没有试过
signal/slot目前有三种调用方式
1.DirectConnection
和以前一样,在emit处直接invoke你的slot 函数,一般情况是sender,receiver在同一线程
2.QueuedConnection
将 发送Event给你的receiver所在的线程
postEvent(QEvent::MetaCall,...)
slot 函数会在receiver所在的线程的event loop中进行处理,一般情况是sender,receiver不在同一线程
3.BlockingQueuedConnection
调 用sendEvent(QEvent::MetaCall,...),在receiver所在的线程处 理完成后才会返回;只能当sender,receiver不在同一线程时才可以
好了,上面的是说为什么不行的,那如果非要在非GUI线程里操作GUI线程里的控件,该怎么做呢?
答案是使用signal/slot。
在线程里的run()里定期emit signal,GUI线程里建立连接,写槽函数,注意connect的第五个参数应该使用Queued方式。
下面列个从QT论坛上找的例子,专门用来解释这个问题的
thread.h:
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
class Thread : public QThread
{
Q_OBJECT
public:
Thread();
signals:
void sendString(QString);
protected:
void run();
};
#endif // THREAD_H
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
#include <QtGui/QTextEdit>
class Thread;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private:
QTextEdit *m_textEdit;
Thread *m_thread;
};
#endif // WIDGET_H
thread.cpp:
#include "thread.h"
#include <QtCore/QTime>
Thread::Thread()
{
}
void Thread::run()
{
while(1)
{
emit sendString(QTime::currentTime().toString("hh:mm:ss.zzz"));
msleep(200);
}
}
widget.h:
#include <QtGui/QHBoxLayout>
#include "widget.h"
#include "thread.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
m_textEdit = new QTextEdit(this);
QHBoxLayout * layout = new QHBoxLayout(this);
layout->addWidget(m_textEdit);
setLayout(layout);
m_thread = new Thread();
connect(m_thread, SIGNAL(sendString(QString)), m_textEdit, SLOT(append(QString)));
m_thread->start();
}
Widget::~Widget()
{
}
main.cpp:
#include <QtGui/QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}这个例子就演示了如何在非GUI线程里调GUI线程里的控件。
边栏推荐
猜你喜欢

How does Mysql query two data tables for the same fields in two tables at the same time

千万级别的表分页查询非常慢,怎么办?

IDEA2021.2安装与配置(持续更新)

解决移动端有纵向滚动条但是不能滚动的问题

Fortify白盒神器20.1.1下载及安装(非百度网盘)

使用pipreqs导出项目所需的requirements.txt(而非整个环境)

五、《图解HTTP》报文首部和HTTP缓存

Eject stubborn hard drives with diskpart's offline command

PowerShell:执行 Install-Module 时,不能从 URI 下载

内存模型之有序性
随机推荐
HCIP实验(06)
Neo4j 4.X:导入OWL文件
2022下半年软考「高项&集成」复习计划ta来喽~
ArcEngine (six) use the tool tool to realize the zoom in, zoom out and translation of the pull box
Evaluate: A detailed introduction to the introduction of huggingface evaluation indicator module
How does Mysql query two data tables for the same fields in two tables at the same time
面试介绍项目经验(转)
ArcEngine(四)MapControl_OnMouseDown的使用
ArcEngine (3) zoom in and zoom out through the MapControl control to achieve full-image roaming
并发之ReentrantLock
"Swordsman Offer" brush questions print from 1 to the largest n digits
sqlite 日期字段加一天
volta管理node版本
MySQL数据库————数据库与vs的连接
HCIA实验(07)
netstat 及 ifconfig 是如何工作的。
ArcEngine(五)用ICommand接口实现放大缩小
redis AOF持久化个人理解
服务器资源监控工具-nmon、nmon_analyser
基于SSM开发的的小区物业管理系统小程序源码