Qt学习记录(14)线程

前言:

我的臀部已经翘到可以顶起一屁股债了

为什么要使用线程

什么时候用线程

复杂的数据处理

头文件.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>//定时器头文件

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void dealTimeout();//定时器槽函数

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QTimer *myTimer;//声明变量
};
#endif // WIDGET_H

.cpp文件 

#include "widget.h"
#include "ui_widget.h"
#include <QThread>
#include <QDebug>

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

    myTimer=new QTimer(this);

    //只要定时器启动,自动触发timeout()
    connect(myTimer,&QTimer::timeout,this,&Widget::dealTimeout);
}

void Widget::dealTimeout()
{
    static int i =0;
    i++;
    //设置LCD的值
    ui->lcdNumber->display(i);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    //如果定时器没有工作
    if(myTimer->isActive()==false)
    {
        myTimer->start(100);
    }
    //非常复杂的数据处理,耗时较长
    QThread::sleep(5);

    //处理完数据,关闭定时器
    myTimer->stop();
    qDebug()<<"over";
}

 现象

忘了录,而且不好展示,当按下start按键的时候,整个页面会卡住,不可移动和点击,LCD也没有变化,5秒后打印"over"

线程旧的用法

 

 添加QThread文件

添加新文件

 注意基类选择object

 .h和.cpp文件改基类和头文件

运行检查是否有错

QThread F1查询 Protected Function

protected:
    //QThread的虚函数
    //线程处理函数
    //不能直接调用,通过start()间接调用
    void run();

 QThread的使用

mythread.h 线程头文件

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);
protected:
    //QThread的虚函数
    //线程处理函数
    //不能直接调用,通过start()间接调用
    void run();
signals:
    void isDone();

};

#endif // MYTHREAD_H

mythread.cpp 线程主文件 

#include "mythread.h"

MyThread::MyThread(QObject *parent) : QThread(parent)
{

}

void MyThread::run()
{
    //很复杂的数据处理
    //需要耗时5s
    sleep(5);

    emit isDone();
}

 widget.h主窗口头文件

添加了线程头文件,线程槽函数,线程停止函数,线程对象

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>//定时器头文件
#include "mythread.h"//线程头文件

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void dealTimeout();//定时器槽函数
    void dealDone();//线程槽函数
    void stopThread();//停止线程槽函数
private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QTimer *myTimer;//声明变量
    MyThread *thread;//线程对象
};
#endif // WIDGET_H

 widget.cpp 主窗口主文件

#include "widget.h"
#include "ui_widget.h"
#include <QThread>
#include <QDebug>

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

    myTimer=new QTimer(this);

    //只要定时器启动,自动触发timeout()
    connect(myTimer,&QTimer::timeout,this,&Widget::dealTimeout);

    //分配空间
    thread = new MyThread(this);

    connect(thread,&MyThread::isDone,this,&Widget::dealDone);
    
    //当按窗口右上角x时,窗口触发destroyed()信号
    connect(this,&Widget::destroyed,this,&Widget::stopThread);
}
void Widget::stopThread()
{
    //停止线程
    thread->quit();
    //等待线程处理完手中工作
    thread->wait();  
}

void Widget::dealDone()
{
    qDebug()<<"it is over";
    myTimer->stop();
}
void Widget::dealTimeout()
{
    static int i =0;
    i++;
    //设置LCD的值
    ui->lcdNumber->display(i);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    //如果定时器没有工作
    if(myTimer->isActive()==false)
    {
        myTimer->start(100);
    }
    //启动线程,处理数据
    thread->start();
}

现象

5秒停止,打印"it is over"

线程新的用法

 

mythread.h头文件

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>

class MyThread : public QObject
{
    Q_OBJECT//如果没有这个宏就会报错
public:
    explicit MyThread(QObject *parent = nullptr);

    //线程处理函数
    void myTimeout();

    void setFlag(bool flag=true);

signals:
    void mySignal();

private:
    bool isStop;


};

#endif // MYTHREAD_H

 

mythread.cpp文件

#include "mythread.h"
#include <QThread>
#include <QDebug>
#include <QMessageBox>

MyThread::MyThread(QObject *parent) : QObject(parent)
{
    isStop=false;
}

void  MyThread::myTimeout()
{
    while(isStop==false)
    {

        QThread::sleep(1);
        emit mySignal();
        //QMessageBox::aboutQt(NULL);

        qDebug()<<"子线程号:"<<QThread::currentThread();
        if(true==isStop)
        {
            break;
        }
    }

}

void MyThread::setFlag(bool flag)
{
    isStop=flag;
}

 

widget.h头文件

#ifndef WIDGET_H
#define WIDGET_H

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

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void dealSignal();
    void dealClose();
signals:
    void startThread();//启动子线程的信号

private slots:
    void on_ButtonStart_clicked();

    void on_ButtonStop_clicked();

private:
    Ui::Widget *ui;
    MyThread *myT;
    QThread *thread;

};
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>


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

    //动态分配空间,不能指定父对象
    //指定父对象后,不能move
    myT =new MyThread;

    //创建子线程
    thread =new QThread(this);

    //把自定义的线程加入到子线程中
    myT->moveToThread(thread);

    connect(myT,&MyThread::mySignal,this,&Widget::dealSignal);

    qDebug()<<"主线程号:"<<QThread::currentThread();

    connect(this,&Widget::startThread,myT,&MyThread::myTimeout);

    connect(this,&Widget::destroyed,this,&Widget::dealClose);

    //线程处理函数内部,不允许操作图形界面

    //connect()第五个参数的作用,连接方式:默认,队列,直接
    //多线程才有意义,
    //默认的时候
    //如果是多线程,默认使用队列
    //如果是单线程,默认使用直接方式
    //队列:槽函数所在线程和接收者一样
    //直接:槽函数所在线程和发送者一样
}

Widget::~Widget()
{
    delete ui;
}

void Widget::dealClose()
{
    on_ButtonStop_clicked();
    delete myT;
}

void Widget::dealSignal()
{
    static int i=0;
    i++;
    ui->lcdNumber->display(i);

}
void Widget::on_ButtonStart_clicked()
{
    if(thread->isRunning()==true)
    {
        return;
    }
    //启动线程,但是没有启动线程处理函数
    thread->start();
    myT->setFlag(false);

    //不能直接调用线程处理函数
    //直接调用会导致线程处理函数和主线程是在同一个线程
    //myT->myTimeout();

    //只能通过 signal-slot方式调用
    emit startThread();
}

void Widget::on_ButtonStop_clicked()
{
    if(thread->isRunning()==false)
    {
        return;
    }
    myT->setFlag(true);
    thread->quit();//线程手头工作处理不完
    thread->wait();
}

现象

 在黑马的视频里面说,线程内部不能处理图形,但是我这里是运行出来的了,QMessageBox,但是后面又出问题,闪退了

线程画图

流程

mythread.h头文件

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QImage>
#include <QObject>

class MyThread : public QObject
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);

    //线程处理函数
    void drawImage();
signals:
    void updateImage(QImage temp);

};

#endif // MYTHREAD_H

mythread.cpp文件

#include "mythread.h"
#include<QPainter>
#include <QPen>
#include <QBrush>
#include <QThread>
MyThread::MyThread(QObject *parent) : QObject(parent)
{

}
void MyThread::drawImage()
{
    //定义QImage绘图设备
    QImage image(500,500,QImage::Format_ARGB32);
    //定义画家,指定绘图设备
    QPainter p(&image);



    //定义画笔对象
    QPen pen;
    pen.setWidth(5);//设置宽度
    //把画笔交给画家
    p.setPen(pen);

    //定义画刷
    QBrush brush;
    brush.setStyle(Qt::SolidPattern);//设置样式
    brush.setColor(Qt::red);//设定颜色
    //把画刷交给画家
    p.setBrush(brush);

    //定义5个点
    QPoint a[] =
    {
        QPoint(qrand()%500,qrand()%500),
        QPoint(qrand()%500,qrand()%500),
        QPoint(qrand()%500,qrand()%500),
        QPoint(qrand()%500,qrand()%500),
        QPoint(qrand()%500,qrand()%500)
    };

    p.drawPolygon(a,5);

    //通过信号发送图片
    emit updateImage(image);

}

widget.h头文件

#ifndef WIDGET_H
#define WIDGET_H

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

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    //重写绘图事件
    void paintEvent(QPaintEvent *);
    void getImage(QImage temp);
    void dealClose();//窗口关闭槽函数

private:
    Ui::Widget *ui;
    QImage image;
    MyThread *myT;//自定义线程对象
    QThread *thread;
};
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QThread>
#include <QPushButton>
#include <QImage>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //自定义类对象,分配空间,不可以指定父对象
    myT=new MyThread;

    //创建子线程
    thread=new QThread(this);

    //把自定义模块添加到子线程
    myT->moveToThread(thread);

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

    //线程处理函数,必须通过signal -solt调用
    connect(ui->pushButton,&QPushButton::pressed,myT,&MyThread::drawImage);
    connect(myT,&MyThread::updateImage,this,&Widget::getImage);
    connect(this,&Widget::destroyed,this,&Widget::dealClose);

}

Widget::~Widget()
{
    delete ui;
}
void Widget::dealClose()
{
    //退出子线程
    thread->quit();
    //回收资源
    thread->wait();

    delete myT;

}
void Widget::getImage(QImage temp)
{
    image=temp;
    update(); //更新窗口,间接调用painEvent()

}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter p(this);//创建画家,指定绘图设备为窗口
    p.drawImage(50,50,image);
}

现象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/643931.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity功能——设置Camera,实现玩家被攻击后晃动效果

一、方法说明&#xff1a; 来源&#xff1a;siki学院&#xff1a;Unity项目捕鱼达人&#xff0c;功能学习记录&#xff1b; 效果摘要&#xff1a;通过调整相机移动&#xff0c;视觉感觉玩家面板剧烈晃动&#xff0c;实现被boss攻击时的震动效果。 使用场景说明&#xff1a; …

串口中断原理及实现

一、串口的原理 SM0、SM1——串行口工作模式 SM0SM1模式特点00模式0移位寄存器方式&#xff0c;用于I/O口扩展01模式18位UART,波特率可变10模式29位UART,波特率为时钟频率/32或/6411模式39位UART,波特率可变 TI、RI——发送、接收中断标志位 TITI0 允许发送>TI1 发送完成后…

python:__set_name__使用

python&#xff1a;__set_name__使用 1 前言 在Python中&#xff0c;我们可以通过__set_name__方法来实现一些特殊的操作。该方法是在定义类的时候被调用&#xff0c;用于设置属性的名称。这样一来&#xff0c;我们就可以在类定义中动态地获取属性的名称&#xff0c;从而更好…

【408精华知识】指令的寻址方式

文章目录 一、指令寻址&#xff08;一&#xff09;顺序寻址&#xff08;二&#xff09;跳跃寻址 二、数据寻址&#xff08;一&#xff09;隐含寻址&#xff08;二&#xff09;立即&#xff08;数&#xff09;寻址&#xff08;三&#xff09;直接寻址&#xff08;四&#xff09;…

在ubuntu22.04里网站源码连不上mysql数据库

在ubuntu22.04里网站源码连不上mysql数据库。后来找到了原因。 连不上的时候有报错信息&#xff1a; ERROR 1698 (28000): Access denied for user rootlocalhost 用在网上搜索该报错信息&#xff0c;找到了两篇有用的文章&#xff0c;用这两篇文章里的处理方法解决了问题。 …

HCIP-Datacom-ARST自选题库__ISIS简答【3道题】

1.IS-1S是链路状态路由协议&#xff0c;便用SPF算法进行路由计算。某园区同时部署了IPv4和IPV6井运行IS-IS实现网络的互联互通&#xff0c;如图所示&#xff0c;该网络IPv4和IPV6开销相同&#xff0c;R1和R4只支持IPV4。缺省情况下&#xff0c;计算形成的IPv6最短路径树中&…

深入理解 Mysql 分层架构:从存储引擎到查询优化器的内部机制解析

一、基础架构 1.连接器 1.会先连接到这个数据库上&#xff0c;这时候接待你的就是连接器。连接器负责跟客户端建立连接、获取权限、维持和管理连接 2.用户密码连接成功之后&#xff0c;会从权限表中拿出你的权限&#xff0c;后续操作权限都依赖于此时拿出的权限,这就意味着当链…

vue 表单些某项 v-if 控制后,想在显示时添加验证

效果: 可以为<el-form-item>添加 key 然后prop正常写就行 (key需要唯一值) <el-form-item label"设置" v-if"advanced_setting" key"threshold" prop"threshold"><el-inputv-model"form_Warning.threshold"p…

亲测使用frp获得访问者真实ip

怎么访问都只有127.0.0.1这个内网ip,获取不到访问者的真实ip 1.打开frp的配置文件(一般是frpc.toml&#xff0c;无需设置frps.toml) 在每一个tcp协议中添加 transport.proxyProtocolVersion "v2" 实例&#xff1a; # frpc.toml [[proxies]] name "web" …

Quartus 联合 ModelSim 仿真 IP 核(RAM)

文章目录 ModelSim 路径设置创建 RAM进行仿真 本文主要介绍如何在包含 IP 核的 Quartus 项目中使用 Modelsim 进行仿真&#xff0c;本文基于 IP 核 RAM: 2-PORT&#xff0c;其他 IP 核类似。 ModelSim 路径设置 点击 Tools->Options 点击 EDA Tool Options&#xff0c;设置…

Baidu Comate For Xcode 你的AI编程助手

前言 Baidu Comate 基于文心大模型&#xff0c;结合百度编程大数据&#xff0c;为你生成优质编程代码 你的AI编程助手&#xff0c;你的编码效率提升好帮手 Baidu Comate 释放“十倍”软件生产力 一、Xcode 安装配置 Baidu Comate 安装 已安装Xcode的情况下&#xff0c;下载B…

Flask实现文件上传/下载【基础版】

目录 前言 一.文件上传 1.1一些<input>相关上传属性 1.1.1multiple 1.1.2accept 1.2Flask后台接收文件提交 1.3Flask后台接收多个文件 二.保护文件上传 2.1限制文件上传大小 2.2验证文件名 2.3验证文件内容 三.文件下载 3.1使用send_file()方法下载文件 前言…

java如何获取IP和IP的归属地?

在Java中&#xff0c;获取IP地址通常指的是获取本地机器的IP地址或者通过某种方式&#xff08;如HTTP请求&#xff09;获取的远程IP地址。代码案例如下: 而要获取IP的归属地&#xff08;地理位置信息&#xff09;&#xff0c;则通常需要使用第三方IP地址查询服务&#xff0c;我…

Advanced Installer 问题集锦

1、界面在主题中显示的图标&#xff0c;如logo、发布者名称、产品名称就算在设计界面时删除&#xff0c;但是下次打开工程依然存在 解决办法&#xff1a;“可见”属性设置为禁用 2、在不关闭软件的情况下&#xff0c;使用"文件->打开"来切换项目&#xff0c;再次…

C++的数据结构(十二):图

在计算机科学中&#xff0c;图是一种非线性数据结构&#xff0c;它表示对象之间的关系&#xff0c;例如通信网络的连接、社交网络中人与人之间的联系&#xff0c;或者是地图上的路径和地标。 图由顶点&#xff08;或称为节点&#xff09;和边组成。边连接着两个顶点&#xff0c…

AI代码生成,真实工程与展望

某AI的代码生成&#xff0c;比另外某ai&#xff0c;略好一丢丢&#xff0c;比实际工程代码呢&#xff0c;差点细节。 所以&#xff0c;这注定是一个过渡的时代&#xff0c;一代过渡的人。 因为更庞大的上下文和知识体系&#xff0c;AI更有能力负责架构&#xff0c;而人类需要…

【openlayers系统学习】1.6下载要素,将要素数据序列化为 GeoJSON并下载

六、下载要素 下载要素 上传数据并编辑后&#xff0c;我们想让用户下载结果。为此&#xff0c;我们将要素数据序列化为 GeoJSON&#xff0c;并创建一个带有 download​ 属性的 <a>​ 元素&#xff0c;该属性会触发浏览器的文件保存对话框。同时&#xff0c;我们将在地图…

【WEEK13】 【DAY4】Shiro Part 4【English Version】

2024.5.23 Thursday Continued from 【WEEK13】 【DAY3】Shiro Part 3【English Version】 Table of Contents 15.6. Integrate Shiro with MyBatis15.6.1. Modify pom.xml15.6.2. Create application.yaml15.6.3. Connect to the database15.6.4. Modify application.propert…

C++:List的使用和模拟实现

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一 list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers …

智能家居6 -- 配置 ini文件优化设备添加

不知道什么是ini的朋友可以先看这篇:一文带你入门ini格式-CSDN博客 准备 如下图: 在src 下面添加 ini.c 在inc 下面添加 ini.h 在 receive_interface.c 里面包含头文件&#xff0c;把之前添加的设备类注释掉 这时候就可以把相关设备的(.c .h)文件给删掉了 如下图: 修改/添…