QT7_视频知识点笔记_5_线程,数据库

news2024/11/15 15:40:52

多线程

两种办法:第一种:Qt4.7之前的线程使用的方法(简单);第二种:Qt4.7之后的(灵活–推荐)----connect最后一个参数的作用:默认连接,队列连接,直接连接
现只举例第二种办法:
主线程:为MyWidget中定时器显示
子线程:为MyWork中的业务处理函数

#include <QThread>


class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();

    // 开始按钮(主线程)
    void slotStart();
    // 关闭按钮(主线程)
    void slotStop();

    // 开始按钮(子线程)
    void slotStart_1();
    // 关闭按钮(子线程)
    void slotStop_1();

    // 定时器
    void slotTimeout();
    // 关闭线程
    void slotCloseThread();

signals:
    void sigWorking();

private:
    Ui::MyWidget *ui;
    QTimer* mytimer;
    MyWork *work;
    QThread* pthread;
};

最主要的部分:1.业务对象(自己写的业务类) 2.子线程类QThread类 3.移动业务对象到子线程moveToThread 4.子线程工作connect

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

    /* 多线程使用注意事项:
     * 1. 业务对象, 构造的时候不能指定父对象
     * 2. 子线程中不能处理ui窗口(ui相关的类)
     * 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口
    */
    mytimer  = new QTimer(this);
    // 1. 业务对象
    work = new MyWork();
    // 2. 子线程类
    pthread = new QThread(this);
    // 3. 移动业务对象到子线程
    work->moveToThread(pthread);
    // 5. 子线程工作
    connect(this, &MyWidget::sigWorking, work, &MyWork::doMyWork);


    connect(ui->start, &QPushButton::clicked, this, &MyWidget::slotStart);
    connect(ui->stop, &QPushButton::clicked, this, &MyWidget::slotStop);

    connect(ui->start_1, &QPushButton::clicked, this, &MyWidget::slotStart_1);
    connect(ui->stop_1, &QPushButton::clicked, this, &MyWidget::slotStop_1);

    // 定时器
    connect(mytimer, &QTimer::timeout, this, &MyWidget::slotTimeout);

    // 窗口析构的时候干掉线程
    connect(this, &MyWidget::destroyed, this, &MyWidget::slotCloseThread);

    qDebug() << QThread::currentThread() << "main thread";

    /* connect 的第 5 参数
     * 1. 自动连接 -- 默认
     *      多线程 -- 指定队列连接
     *      单线程 -- 指定直接连接
     * 2. 队列连接 -- 多线程
     *      槽函数在信号接受者(receiver)所在的线程中执行
     * 3. 直接连接 -- 单线程
     *      信号和槽函数在同一个线程中执行
    */
}

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

void MyWidget::slotStart()
{
    if(mytimer->isActive() == true)
    {
        qDebug() << "mytimer->isActive() == true";
        return;
    }
    qDebug() << "mytimer->start";
    mytimer->start(500);

}

void MyWidget::slotStop()
{
    mytimer->stop();    //此按钮主线程(MyWidget计时器)暂停
}

void MyWidget::slotStart_1()
{
    if(pthread->isRunning())
    {
        qDebug() << "pthread->isRunning()";
        return;
    }

    qDebug() << "pthread->start";
    // 4. 启动子线程
    pthread->start();
    work->setFlage(false);
    // 发信号, 让子线程工作
    emit sigWorking();
}

void MyWidget::slotStop_1()
{
    qDebug() << "slotStop_1";
    work->setFlage(true);
    pthread->quit();

}
void MyWidget::slotTimeout()
{
    static int num = 0;
    ui->lcdNumber->display(num++);
}

void MyWidget::slotCloseThread()
{
    work->setFlage(true);

    pthread->quit();
    pthread->wait();    // 等待线程手头上的工作处理完成
}

#include <QThread>

class MyWork : public QObject
{
    Q_OBJECT
public:
    explicit MyWork(QObject *parent = 0);

    // 业务处理函数
    void doMyWork();

    void setFlage(bool bl);

signals:
    void sigDone();

public slots:
private:
    bool isStop;
};

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

void MyWork::doMyWork()
{
    qDebug() << "isStop1:"<<isStop;
    while(!isStop)
    {
        qDebug() << "isStop2:"<<isStop;
        if(isStop)
        {
            break;
        }
        // 操作
        QThread::sleep(1);  // 当前线程处理操作用了1s
        // 每执行一次循环发一次信号
        emit sigDone();
        qDebug() << QThread::currentThread() << "sub thread";
        // QMessageBox::aboutQt(NULL);

    }
}

void MyWork::setFlage(bool bl)
{
    qDebug() << "setFlage:"<<bl;
    isStop = bl;
}

最后效果:
在这里插入图片描述

数据库操作

1.QSqlDataBase:数据库类,用来添加数据库
pro文件中添加sql
添加头文件:
#include <QSqlDatabase>
#include <QMessageBox>
#include <QSqlError>


	//添加一个mysql数据库
    //1.QSQLITE-->XX.db文件     2.QMYSQL
    //QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");        //使用QMYSQL暂时还有一点问题,这里使用QSQLITE,本地的db文件做
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
	db.setDatabaseName("TestResult.db");//连接的数据库名TestResult.db

    //打开数据库
    if(db.open()==false)
    {
        //弹窗提示
        QMessageBox::warning(this,"warning",db.lastError().text());
    }else{
        QMessageBox::warning(this,"warning","db.open");
    }
2.QSqlQuery:数据库查询类,(需要会一些SQL语句)

添加一条记录:

//增删查改 ...
    qDebug()<<"QSqlQuery query";
    //添加一条记录    QSqlQuery需要用到SQL语句
    QSqlQuery query;
    QString sql = "insert into people(name,age) values('zzz',123)";     //需要db文件中有people表,表中有name和age字段
    query.exec(sql);

批处理方式一:

    //2.批处理方式一:预处理    ---通配符:‘?’,odbc风格的通配符
    query.prepare("insert into people(name,age) values(?,?)");      //要注意格式不能写错了
    //添加绑定数据,需要跟上面的通配符对应起来
    QVariantList nameList;          //Variant中可以放任意的数据
    nameList << "aax" << "bbx" << "ccx";
    query.addBindValue(nameList);

    QVariantList ageList;
    ageList << 12 << 13 << 14;
    query.addBindValue(ageList);
    //执行批处理
    query.execBatch();

在这里插入图片描述

批处理方式二:

    //3.批处理方式二:oracle风格的通配符(更加灵活,推荐)
    //定义方式:  :+自定义名
    query.prepare("insert into people(name,age) values(:name,:age)");
    //添加绑定数据,需要跟上面的通配符对应起来
    QVariantList nameList;          //Variant中可以放任意的数据
    nameList << "aa" << "bb" << "cc";
    query.bindValue(":name",nameList); //通配符名字,通配符

    QVariantList ageList;
    ageList << 11 << 22 << 33;
    query.bindValue(":age",ageList);
    //执行批处理
    query.execBatch();

在这里插入图片描述
数据库查询:

//4.数据库查询
     //4.数据库查询
    query.exec("select * from people");
    //如何把返回的值取出来(⭐)
    while(query.next()) //如果query不为空,(遍历每一条记录)
    {
        //0 --第一个字段的索引值
        qDebug()<<query.value(0).toString()	//这个0是指exec取出的表中第一个数据类型
                <<query.value("age").toInt();
    }

//    //或者,
//    query.exec("select age from people");
//    while(query.next()) //如果query不为空,(遍历每一条记录)
//    {
//        //0 --第一个字段的索引值
//        qDebug()<<query.value(0).toInt();   //这样的话此处query.value(0)就为age
//    }

在这里插入图片描述

3.QSqlTableModel:数据模型。不需要掌握SQL语句,已经在内部做了SQL语句的封装。(创建对象,设置数据库表,将model放入view(QTableView)中,显示(查询)数据,设置表头(setHeadData),setEditStartegy()
//头文件
#include <QSqlTableModel>   //数据模型
//显示模型中的数据则需要使用视图:QTableView - QSqlTableModel
// qt中的 model-view模型

//前提条件:在步骤1中QSqlDataBase,正常打开数据库
	//1.实例化model
    model = new QSqlTableModel(this);
    //2.将模型设置到视图中
    ui->tableView->setModel(model);		//在ui中添加
    //3.给model设置数据库表 -- 前提条件:数据库
    model->setTable("people");
    //4.查询表,只有进行查询,model中才会有数据
    model->select();
    //设置(更改)表头
    model->setHeaderData(0,Qt::Horizontal,"编号");      //第一个参数section是字符串截取

在这里插入图片描述
需要注意的地方:ui修改自动同步到数据库的风险

	//需要注意的是,在ui中修改的话数据库默认也随之更改
    //5.解决办法:设置提交模式,F1查看函数用法,设置为手动提交,在UI上修改之后需要手动提交DB文件才会进行修改。
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);

.......

//在UI中增加一个提交UI修改的按钮,一个撤销的按钮

void Widget::on_pushButton_clicked()
{
    qDebug()<<"on_pushButton_clicked";
    model->submitAll();
}

void Widget::on_pushButton_revent_clicked()
{
    qDebug()<<"on_pushButton_revent_clicked";
    model->revertAll(); //撤销步骤
    model->submitAll(); //提交步骤  --更新数据模型
}

查询数据,此处举例按名字查询,UI上增加输入框和查询按钮


void Widget::on_pushButton_search_clicked()
{
    qDebug()<<"on_pushButton_revent_clicked";
    QString name = ui->lineEdit->text();    //获取需要查询的人名

    //设置过滤条件查询
    //与SQL语句对比:“select * from aa where name = 'xiaoming'
    QString sql = QString ("name = '%1'").arg(name);
    model->setFilter(sql);
    //重新查询
    model->select();

}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3使用mitt.js进行各种组件间通信

我们在vue工程中&#xff0c;除开vue自带的什么父子间&#xff0c;祖孙间通信&#xff0c;还有一个非常方便的通信方式&#xff0c;类似Vue2.x 使用 EventBus 进行组件通信&#xff0c;而 Vue3.x 推荐使用 mitt.js。可以实现各个组件间的通信 优点&#xff1a;首先它足够小&…

从业务角度来看,DevOps 是什么?

如果您在我们的应用程序名称中看到“DevOps”&#xff0c;这意味着我们必须正确解释该术语&#xff0c;我们会这样做&#xff0c;但角度会有所不同。让我们从业务角度看看 DevOps 是什么。 通用名称 首先你应该知道&#xff0c;DevOps 没有明确的定义。是的。 大多数情况下&a…

分类和品牌关联

文章目录 1.数据库表设计1.多表关联设计2.创建表 2.使用renren-generator生成CRUD1.基本配置检查1.generator.properties2.application.yml 2.生成代码1.进入localhost:81生成代码2.将main目录覆盖sunliving-commodity模块的main目录 3.代码检查1.注释掉CategoryBrandRelationC…

使用xsd验证xml格式的正确性

1.1 基础知识介绍 XML简介&#xff1a;XML是可扩展标记语言&#xff08;eXtensible Markup Language&#xff09;的缩写&#xff0c;它是一种数据表示格式&#xff0c;可以描述非常复杂的数据结构&#xff0c;常用于传输和存储数据。xml文件、xml消息。XSD简介&#xff1a;是X…

JS对象超细

目录 一、对象是什么 1.对象声明语法 2.对象有属性和方法组成 二、对象的使用 1.对象的使用 &#xff08;1&#xff09;查 &#xff08;2&#xff09;改 &#xff08;3&#xff09;增 &#xff08;4&#xff09;删&#xff08;了解&#xff09; &#xff08;5&#xf…

九州未来十二周年丨聚力同行,奔赴智能新未来

九州未来迎来十二周年&#xff01; 从国内首批提供 OpenStack 云服务的专业公司&#xff0c; 经过十二年的发展&#xff0c; 现今成长为开放智能云边架构引领者。 在这十二年的时间中&#xff0c; 九州未来持续创新&#xff0c;步履不停&#xff0c; 打造成熟的云基础设施…

【软件测试】软件测试基础理论

目录 软件测试简介软件产生过程小结 主流测试掌握技能功能测试功能测试的注意事项 自动化测试自动化测试的优势自动化测试的限制和适用性&#xff1a;自动化测试的注意事项 接口测试接口测试通常可以涵盖以下方面接口测试的注意事项 性能测试性能测试的几个方面性能测试的注意事…

JavaSE:Clonable接口、浅拷贝与深拷贝

1、引言 我们在学习的数组时&#xff0c;就了解到了数组克隆方法&#xff0c;可以通过数组克隆方法来拷贝一个一模一样的数组&#xff1a; 那对于自定义类型中有没有克隆方法呢&#xff1f;答案是有的&#xff01; 就让这篇文章来帮助大家学习自定义类型的拷贝&#xff01; …

基于深度学习的表情识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着人工智能技术的快速发展&#xff0c;表情识别成为了人机交互领域的一个研究热点。表情识别技术旨…

docker redis 持久化

1、拉取redis镜像 docker pull redis:latest 2、 mkdir /data/redis 3、填充redis.conf文件及根据需求修改相应的配置 •通过官网地址找到对应版本的配置文件 •将配置信息复制到redis.conf中 •常见的修改配置 https://redis.io/docs/latest/operate/oss_and_stack/managem…

K8s 高级调度

文章目录 K8s 高级调度CronJobinitContainerTaint 和 Toleration污点&#xff08;Taint&#xff09;容忍&#xff08;Toleration&#xff09; AffinityNodeAffinityPodAnffinity 和 PodAntiAffinity 总结 K8s 高级调度 CronJob 在 k8s 中周期性运行计划任务&#xff0c;与 li…

获取支持Windows7的最新Edge离线版本

从110版本开始&#xff0c;微软Edge和谷歌停止了对Win7、Win8/8.1的支持&#xff0c;后续又发布了几版安全更新&#xff0c;截止目前为止&#xff0c;能支持Win7的版本是 109.0.1518.140。 如果你想用最新版本谷歌浏览器&#xff0c;可以考虑下Supermium&#xff0c;这个浏览器…

Flask CORS: 解决跨域资源共享问题的利器

文章目录 安装和启用 CORS配置 CORS拓展 在本文中&#xff0c;我们介绍了如何使用 Flask-CORS 扩展来解决跨域问题。Flask-CORS 是一个方便的工具&#xff0c;可以帮助我们轻松地实现跨域资源共享支持。 安装和启用 CORS 要开始使用 Flask-CORS&#xff0c;我们需要先安装它。…

一些常见的程序设计问题

秒杀 redis缓存库存 1.判断库存名额是否充足&#xff0c;2.进行扣减 为了防止超卖&#xff0c;必须保证这两部的原子性 库存扣减后发送mq消息&#xff0c;去异步执行创建订单流程&#xff0c;创建订单失败会造成少卖。可加重试机制&#xff0c;对多次重试依旧失败的&#xff…

react 函数组件 开发模式默认被渲染两次

这是 React 刻意为之&#xff0c;函数式组件应当遵从函数式编程风格&#xff0c;每次执行应该是无副作用的(no sideEffect)&#xff0c;在 dev 下多次渲染组件&#xff0c;是为了防止开发者写出有问题的代码。 用 React 写函数组件&#xff0c;如何避免重复渲染&#xff1f; -…

【BUG】流式响应requests得到: ping - 和时间戳

前情提要 运行Langchain-Chatchat项目&#xff0c;使用自定义请求访问API Server流式输出 报错展示 b: ping - 2024-05-22 00:46:04.83252000:00\r\n\r\n报错原因 这通常是由于 Server-Sent Events (SSE) 实现中使用的“心跳”机制&#xff0c;以确保连接保持活跃。一些 SSE…

使用python实现socket进行消息传输-demo

Socket 是什么 Socket 是一种在计算机网络中用于实现进程间通信的一种机制。它是网络编程中的重要概念&#xff0c;通过它可以在不同的计算机之间进行数据传输和通信。Socket 可以用于实现各种网络应用&#xff0c;包括客户端-服务器模型、P2P 应用等。基本上&#xff0c;Sock…

新零售数据中台:构建零售业高效率、智能化的数据处理平台_光点科技

随着互联网技术的快速发展和移动支付、大数据等技术的广泛应用&#xff0c;零售行业已经逐渐从传统零售向新零售模式转变。在这个变革的时代背景下&#xff0c;新零售数据中台应运而生&#xff0c;它作为零售行业数据资源的整合与智能分析的核心载体&#xff0c;成为推动零售行…

基于消息中间件的异步通信机制在系统解耦中的优化与实现

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

重生之我要精通JAVA--第五周笔记

文章目录 APIJDK7时间Date时间类CalendarSimpleDateFormat 类SimpleDateFormat 类作用 JDK8时间Zoneld时区 包装类Integer成员方法 Arrays Lambda表达式标准格式注意点好处省略写法 集合进阶Collection迭代器遍历Collection集合获取迭代器Iterator中的常用方法细节注意点 增强f…