QT 多线程的两种实现方法


源文件类

在这里插入图片描述
widget类为主线程,mythread为待创建的子线程类
在这里插入图片描述
点击按钮线程开始执行(针对方法一,方法二忽略图形界面)

实现方法 1

widget.h

#include <QWidget>
#include <QThread>
#include "mythread.h"

class Widget : public QWidget
{
    Q_OBJECT
public:
    QThread * thread; // 子线程
    mythread * mth; // 子线程模块
    void closeThread();  // 关闭子线程
};

注: 上面省略掉无关代码

widget.cpp

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. 自定义线程模块 设置该线程需要完成的任务
    mth = new mythread;

    // 2. 创建子线程 (理解为线程管理者)
    thread = new QThread(this);

    // 3. 将准备好的线程类和子线程关联
    mth->moveToThread(thread);

    // 4. 启动子线程,但是,并没有启动线程处理函数
    thread->start();

    // 5. 线程处理函数需要通过 信号-槽 调用
    connect(ui->pushButton, &QPushButton::pressed, mth, &mythread::printInfo);

    // 6. 关闭线程
    connect(this, &Widget::destroyed, this, &Widget::closeThread);
}
// 关闭线程函数
void Widget::closeThread()
{
    thread->quit(); // 退出子线程
    thread->wait(); // 回收线程资源
    delete mth; // 释放线程模块内存
}

mythread.cpp

#include "mythread.h"
#include <QDebug>
mythread::mythread(QObject *parent) : QObject(parent)
{}

void mythread::printInfo()
{
     qDebug()<<"线程正在执行..."<<endl;
//   if(true)
     //     exit(1);
}

实现方法 2

这里忽略掉ui界面

widget.h

#include <QWidget>
#include "mythread.h"

class Widget : public QWidget
{
    Q_OBJECT
public:
    mythread * thread; // 声明一个线程类对象

    void closeThread(); // 关闭线程
};

注: 省略掉无关代码

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QThread>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. 创建线程对象
    thread = new mythread(this);

    // 2. 会间接调用mythread::run()线程处理函数开始处理数据
    thread->start();

    // 3. 线程处理函数需要通过 信号-槽 调用
    connect(thread, &mythread::isDone,this,&Widget::closeThread);
}
// 关闭线程函数
void Widget::closeThread()
{
    thread->quit(); // 退出子线程
    thread->wait(); // 回收线程资源
    delete thread; // 释放线程模块的内存
}

mythread.h

#include <QThread>

class mythread : public QThread
{
    Q_OBJECT
protected:
    //QThread的虚函数,也是线程处理函数
    //不能直接调用,通过start()间接调用,因为这是个protected函数
    void run();

signals:
    void isDone(); // 线程功能执行完毕
};

mythread.cpp

#include "mythread.h"
#include <QDebug>
mythread::mythread(QObject *parent) : QThread(parent)
{}

void mythread::run()
{
     for(int i = 0; i < 100000000; i++)
        qDebug()<<"线程正在执行..."<<endl;
     
     qDebug()<<"数据处理完毕,我要发出退出信号的"<<endl;
     emit isDone(); // 发送执行完毕信号
}

注意: mythread类的继承对象时QThread

总结

  • 注意第一个方法里面线程继承的是QObject类,而方法二里面继承的类是QThread
  • 方法一种thread->start()会启动线程但不会启动线程处理函数,方法二中会直接调用mythread::run(),且run就是线程处理函数
  • 方法一中线程处理函数可以自定义,方法二中线程处理函数固定是run()不能额外自定义
  • 方法二只需创建线程对象,然后start调用线程函数,最后关闭线程,操作比较简单;方法二需要创建两个对象然后关联,调用线程处理函数需要信号和槽触发,实现比较复杂。
  • 方法一是4.7版本之前的使用方法,方法二是4.7之后的使用方法。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: QTableWidget是Qt提供的用于展示表格数据的控件,遍历行可以使用QTableWidget的rowCount()和item()方法多线程是指同时执行多个任务,可以通过QThread类来实现多线程操作。 若要在多线程中遍历QTableWidget的行,可以考虑以下步骤: 1. 创建一个继承自QThread的自定义线程类,例如MyThread。 2. 在MyThread类中添加一个成员变量用于存储QTableWidget的行数。 3. 重写MyThread类的run()方法,在该方法中使用rowCount()方法获取QTableWidget的行数,并将其存储在成员变量中。 4. 在MyThread类的run()方法中使用另外一个循环遍历QTableWidget的行。遍历时可以使用item()方法获取每一行的单元格数据,并进行相应的处理。 5. 在主线程中,实例化一个MyThread对象,并调用start()方法启动多线程。 6. 可以通过信号和槽机制,将MyThread中遍历得到的数据传递给主线程进行后续处理。 举例代码如下: ```cpp #include <QTableWidget> #include <QThread> class MyThread : public QThread { Q_OBJECT public: explicit MyThread(QTableWidget *widget, QObject *parent = nullptr) : QThread(parent), m_widget(widget) {} protected: void run() override { int rowCount = m_widget->rowCount(); for (int row = 0; row < rowCount; ++row) { for (int column = 0; column < m_widget->columnCount(); ++column) { QTableWidgetItem *item = m_widget->item(row, column); // 处理单元格数据 // ... } } // 遍历完成后,发送信号通知主线程 emit finished(); } signals: void finished(); private: QTableWidget *m_widget; }; int main() { QTableWidget *tableWidget = new QTableWidget; // 初始化QTableWidget MyThread *thread = new MyThread(tableWidget); QObject::connect(thread, &MyThread::finished, [](){ // 多线程中遍历QTableWidget的行操作完成后的处理 // ... }); thread->start(); // 主线程的其他操作 return 0; } ``` 以上是一种简单的多线程遍历QTableWidget的行的实现方式。由于多线程编程较为复杂,需要考虑线程同步、内存管理等问题,请在实际应用中根据具体情况进行相应调整。 ### 回答2: 在QTableWidget中遍历行的过程中使用多线程可以提高程序运行的效率和响应速度。多线程允许程序同时执行多个任务,因此可以让遍历行的任务与其他任务并行执行,从而减少遍历的时间。 首先,我们需要创建一个继承自QThread的自定义线程类。在该线程类中,我们可以重写其run()方法,来执行遍历行的任务。在run()方法中,我们使用循环遍历QTableWidget的每一行,然后处理每一行的数据。 接下来,我们可以在主程序中创建该自定义线程类的实例,并通过调用start()方法来启动线程。线程启动后,会在后台运行,与主线程分离,从而不会阻塞主程序的执行。 在遍历行的任务中,我们可以使用QTableWidget的rowCount()方法来获取表格的行数,然后使用item()方法来获取每一行的单元格数据。对于需要对单元格进行操作的情况,可以使用另一个自定义的槽函数来处理,然后将其与相应的信号连接起来。 需要注意的是,在多线程的情况下,对表格数据的修改可能会引发线程安全的问题。为了解决这个问题,我们可以使用QMutex来保护共享数据的访问,以确保数据的一致性和完整性。 总结起来,通过在QTableWidget的遍历行任务中使用多线程,我们可以提高程序的运行效率,并充分利用多核处理器的优势。但是需要注意线程安全的问题,确保对共享数据的访问是线程安全的。 ### 回答3: 在Qt中,QTableWidget是一个功能强大的控件,用于显示和编辑带有行和列的表格数据。QTableWidget可以通过以下代码进行行的遍历: ``` for(int i=0; i<ui->tableWidget->rowCount(); i++) { // 获取当前行的所有单元格数据 QTableWidgetItem* item1 = ui->tableWidget->item(i, 0); QTableWidgetItem* item2 = ui->tableWidget->item(i, 1); // ... // 处理获取到的数据 } ``` 这段代码将逐行遍历QTableWidget的行,并获取每一行的所有单元格数据。你可以通过item()方法访问每个单元格的数据。然后,你可以使用得到的数据进行相应的处理。 使用多线程进行QTableWidget的遍历时,需要特别注意线程安全性。Qt提供了一种线程间通信的机制,可以使用信号和槽机制在多线程之间传递数据。你可以将遍历行的代码放在一个单独的线程中执行,然后通过信号和槽来传递数据。 首先,在你的代码中创建一个自定义线程类,重写run()方法,将遍历行的代码放在其中: ``` class MyThread : public QThread { Q_OBJECT public: void run() override { for(int i=0; i<ui->tableWidget->rowCount(); i++) { // 获取当前行的所有单元格数据 QTableWidgetItem* item1 = ui->tableWidget->item(i, 0); QTableWidgetItem* item2 = ui->tableWidget->item(i, 1); // ... // 处理获取到的数据 // ... // 发送信号,将数据传递给主线程 emit sendRowData(/* 将获取到的数据传递给主线程 */); } } signals: void sendRowData(/* 定义信号的参数 */); }; ``` 然后,在主线程中创建一个MyThread对象,连接其sendRowData信号到一个槽函数,接收从子线程发出的数据: ``` MyThread* thread = new MyThread(); connect(thread, &MyThread::sendRowData, this, &MainWindow::receiveRowData); thread->start(); ``` 最后,在槽函数receiveRowData()中,接收并处理子线程发出的数据: ``` void MainWindow::receiveRowData(/* 定义槽函数的参数 */) { // 在主线程中处理从子线程接收到的数据 // ... } ``` 通过这种方式,你可以在多线程环境中遍历QTableWidget的行,并在主线程中处理接收到的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值