做了个Excel表格数据读取并显示的小软件,发现QT的程序主界面在点击按钮加载表格数据时候出现卡顿。
初步分析是加载表格数据并进行数据转换时花费了大量时间,这是由于没有做多线程导致界面出现卡顿。
多线程如何做呢,简单来说就是将读取处理数据和显示数据两个步骤分离,这属于异步操作。
前台UI按钮触发-emit信号-后台处理数据槽函数接收-处理完数据-后台emit信号-前台接受后更新展示数据。
1. .pro文件中
QT + = concurrent
2.MainWindow.h中声明一个新线程
#include <QThread>
public:
QThread *mythread;
BackGround *myBackGround;//后台的Object类
需要特别指出的是,后台BackGround类必须继承Object类,因moveToThread是Object类中定义的。class BackGround:public Object。
如果是界面类将创建不了多线程,如class BackGround:public Widget,QT明确不支持界面类实例化。
如果涉及多界面的数据交互,建议新建一个C++ Class继承自QObject。
2.MainWindow.c的构造函数中新建对象
mythread = new QThread;
myBackGround = new BackGround;
myBackGround -> moveToThread(mythread)
3,MainWindow.c有两个成员函数
//点击路径选择按钮,选择一个路径,从该路径中读取文件
connect(select_file_Button,SIGNAL(clicked()),this,SLOT(getDir()));
//将路径作为信号发送给myBackGround,后续步骤在新线程处理了
connect(this,SIGNAL(s_getDir(QString)),myBackGround,SLOT(readData(QString)));
//处理数据结束,发送结束信号给前台显示
connect(myBackGround,SIGNAL(readFinished()),this,SLOT(showFinished()));
readData(QString)函数是后台BackGround类的成员函数(槽函数), 因为这个对象已经 moveToThread()放到myBackThread线程了,所以readData函数执行时并不影响界面操作。
以上就是利用多线程操作实现程序运行界面不卡顿的基本原理。
但是新问题又出现了,由于自定义了一些类用于存放数据,并且使用signal/slot在多界面间数据交互,在调试时候出现了错误:
QObject::connect: Cannot queue arguments of type 'TextAndNumber' (Make sure 'TextAndNumber' is registed using qRegisterMetaType().)
下一篇将解决这个问题。