QT程序主界面运行卡顿如何解决

做了个Excel表格数据读取并显示的小软件,发现QT的程序主界面在点击按钮加载表格数据时候出现卡顿。

初步分析是加载表格数据并进行数据转换时花费了大量时间,这是由于没有做多线程导致界面出现卡顿。

多线程如何做呢,简单来说就是将读取处理数据和显示数据两个步骤分离,这属于异步操作

前台UI按钮触发-emit信号-后台处理数据槽函数接收-处理完数据-后台emit信号-前台接受后更新展示数据。

2021062522082364.png

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。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ltcG9ydF9uZXc=,size_16,color_FFFFFF,t_70

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().)

下一篇将解决这个问题。

 

  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中,在线程中创建UI控件时,如果耗时较长,会导致界面卡顿,影响用户体验。为了解决这个问题,可以在子线程中创建UI控件,然后将UI控件通过信号槽机制传递给线程,从而实现界面卡顿。 具体步骤如下: 1. 在子线程中创建UI控件。 2. 将UI控件通过信号槽机制发送给线程。 3. 在线程中接收信号,将UI控件添加到窗口中。 以下是示例代码: ``` c++ // 在子线程中创建按钮 QPushButton* button = new QPushButton("Button"); // 发送信号,将按钮传递给线程 emit createButton(button); ``` 在上述示例代码中,我们在子线程中创建了一个QPushButton对象,然后通过信号槽机制将按钮传递给线程。具体来说,我们定义了一个createButton信号,它有一个QPushButton指针参数,表示需要在线程中创建的按钮。在子线程中,当我们创建了按钮后,就通过emit发射createButton信号,从而将按钮传递给线程。 在线程中,我们需要连接createButton信号和槽函数,将传递过来的按钮添加到窗口中。具体来说,我们可以在窗口的构造函数中连接createButton信号和槽函数,如下所示: ``` c++ // 在窗口的构造函数中连接信号和槽函数 connect(this, &MainWindow::createButton, this, &MainWindow::addButton); ``` 在上述代码中,我们将createButton信号和槽函数addButton连接起来,表示当子线程中创建了按钮并发射createButton信号时,会触发addButton槽函数的执行。 最后,我们需要实现addButton槽函数,将传递过来的按钮添加到窗口中,如下所示: ``` c++ // 将传递过来的按钮添加到窗口中 void MainWindow::addButton(QPushButton* button) { QVBoxLayout* layout = new QVBoxLayout(this); layout->addWidget(button); setLayout(layout); } ``` 在上述代码中,我们将传递过来的按钮添加到窗口的布局中,从而实现了在子线程中创建UI控件,并在线程中添加UI控件的功能,避免了界面卡顿的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值