Qt—(Qt线程,Qt进程,,QT与sqlite数据库)

发布于:2025-06-22 ⋅ 阅读:(14) ⋅ 点赞:(0)

一 Qt线程与进程概述

线程与进程对比

特性 线程 (QThread) 进程 (QProcess)
内存空间 共享父进程内存 独立内存空间
创建开销 小 (几MB) 大 (几十MB)
通信方式 共享内存/信号槽 管道/套接字/文件
崩溃影响 导致整个进程终止 仅自身终止
适用场景 高并发任务、计算密集型 隔离第三方应用、安全需求

二 Qt线程

1. 基本概念

  • 线程:程序执行的最小单元,共享相同内存空间

  • QThread:Qt中线程管理的核心类

  • 线程安全:多线程访问共享资源时需同步

 2. 创建方式(四种)

  • 继承QThread类,重写run()方法

  • 使用moveToThread将一个继承QObject的子类对象移至线程,内部槽函数均在子线程中执行

  • 使用QThreadPool,搭配QRunnable (线程池)

  • 使用QtConcurrent(线程池)

n. 线程创建

1. QThread,重写run()

#include <QThread>
#include <QDebug>

class WorkerThread : public QThread {
    Q_OBJECT
protected:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Thread working:" << i;
            sleep(1);  // 模拟耗时操作
        }
    }
};

// 使用
int main() {
    WorkerThread thread;
    thread.start();  // 启动线程
    thread.wait();   // 等待线程结束
    return 0;
}

2. moveToThread

#include <QObject>
#include <QThread>
#include <QDebug>

class Worker : public QObject {
    Q_OBJECT
public slots:
    void doWork() {
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Worker in thread:" << QThread::currentThreadId();
            QThread::sleep(1);
        }
        emit workDone();
    }
signals:
    void workDone();
};

// 使用
int main() {
    QThread thread;
    Worker worker;
    
    worker.moveToThread(&thread);  // 关键步骤
    
    QObject::connect(&thread, &QThread::started, &worker, &Worker::doWork);
    QObject::connect(&worker, &Worker::workDone, &thread, &QThread::quit);
    
    thread.start();
    thread.wait();
    return 0;
}

3. QThreadPool(线程池)

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QThreadPool"
#include "MyTask.cpp"

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

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mytask.cpp"
#include "QThreadPool"

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

    //新建10个任务,提交给线程池
    //方式1: 全局线程池:一个项目中只有一个线程池,有时候整个项目有有可能有多个
     //QThreadPool *pool =    QThreadPool::globalInstance();
    //方式2:新建线程池
   QThreadPool *pool = new QThreadPool;
    for(int i=0;i<10;i++){

         pool->start( new MyTask());
    }


}

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



}

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




#include <QRunnable>
#include <QDebug>
#include <QThread>
class MyTask : public QRunnable
{
    //重写run方法
    void run() override
    {
        qDebug()<< QThread::currentThread() << "running .....";
    }

};

4. QtConcurrent(线程池)

三 Qt进程

1. 基本概念

  • 进程:独立内存空间的程序实例

  • QProcess:用于启动和控制外部程序

进程是一个应用程序被操作系统拉起来加载到内存之后从开始执行到执行结束的这样一个过程。简单来说,进程是程序(应用程序,可执行文件)的一次执行。进程通常由程序、数据和进程控制块(PCB)组成。比如双击打开一个桌面应用软件就是开启了一个进程。

传统的进程有两个基本属性:可拥有资源的独立单位;可独立调度和分配的基本单位。对于这句话我的理解是:进程可以获取操作系统分配的资源,如内存等;进程可以参与操作系统的调度,参与CPU的竞争,得到分配的时间片,获得处理机(CPU)运行。

进程在创建、撤销和切换中,系统必须为之付出较大的时空开销,因此在系统中开启的进程数不宜过多。比如你同时打开十几个应用软件试试,电脑肯定会卡死的。于是紧接着就引入了线程的概念

四 sqlite数据库

  sqlite十个轻量级的数据库,如果要进行嵌入式的开发,像mysql,与Oracle像这样的中大型关系库是不太现实的,因为嵌入式大部分的工作,还是以轻量级的项目为主,尽可能的节约空间,完成项目,sqlite可以不用他的专属服务器就可以使用,它可以以一个文件为库,可以还可以用sql的语句,兼顾效率的同时,也极致的轻量化。

  在此我认为只需要写两个项目即可,一是如何链接数据库,二是如何进行增删改查。

1. 连接数据库

其实我建议将连接数据库的语句单独写个类出来,这样简化操作,上上选。

1. 在我的project.pro的上方添加 

QT       += core gui sql 

2. 引入头

#include <QSqlDatabase>
#include <QSqlError> //sql错误信息头文件
#include <QSqlQuery> //sql查询头文件
  QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

    // 链接数据库
    db.setDatabaseName("D:/360MoveData/Users/HP/Desktop/sqlite_db/test.db");
    if (db.open() == false)
    {
        qDebug() << "数据库打开失败";
        return;
    }
    else
    {
        qDebug() << "数据库打开成功";
        // 新建table
        QSqlQuery query;
        QString sql = "create table if not exists user(id int primary key, name varchar(20))";
        if (query.exec(sql))
        {
            qDebug() << "表格创建成功";
            // 向user插入数据
            sql = "insert into user(id, name) values(1, '张三')";
            if (query.exec(sql))
            {
                qDebug() << "数据插入成功";
                // 查询数据
                sql = "select * from user";
                if (query.exec(sql))
                {
                    qDebug() << "数据查询成功";
                    // 输出到qDebug
                    while (query.next())
                    {
                        qDebug() << query.value(0).toInt() << query.value(1).toString();
                    }
                }
                else
                {
                    qDebug() << "数据查询失败";
                }
            }
            else
            {
                qDebug() << "数据插入失败";
            }
        }
        else
        {
            qDebug() << "表格创建失败";
            qDebug() << query.lastError().text();
        }
    }
}

2. 增删改查示例

这个写了个dao来进行数据库的处理,相信大家可以看的懂,其实不难。仔细看一看。

#include "studentdao.h"

/**
 * @brief 构造函数
 * 获取数据库连接
 */
StudentDAO::StudentDAO()
    : m_db(DatabaseManager::getInstance()->getDatabase())
{
}

/**
 * @brief 添加学生
 * @param student 学生对象
 * @return 添加成功返回true,否则返回false
 */
bool StudentDAO::addStudent(const Student &student)
{
    if (!m_db.isOpen())
    {
        qDebug() << "添加学生失败:数据库未连接";
        return false;
    }

    QSqlQuery query(m_db);
    // 使用参数化查询,防止SQL注入
    query.prepare("INSERT INTO student (id, name) VALUES (:id, :name)");
    query.bindValue(":id", student.id());
    query.bindValue(":name", student.name());

    if (query.exec())
    {
        qDebug() << "添加学生成功:ID=" << student.id() << ", 姓名=" << student.name();
        return true;
    }
    else
    {
        qDebug() << "添加学生失败:" << query.lastError().text();
        return false;
    }
}

/**
 * @brief 删除学生
 * @param id 学生ID
 * @return 删除成功返回true,否则返回false
 */
bool StudentDAO::deleteStudent(int id)
{
    if (!m_db.isOpen())
    {
        qDebug() << "删除学生失败:数据库未连接";
        return false;
    }

    QSqlQuery query(m_db);
    query.prepare("DELETE FROM student WHERE id = :id");
    query.bindValue(":id", id);

    if (query.exec())
    {
        if (query.numRowsAffected() > 0)
        {
            qDebug() << "删除学生成功:ID=" << id;
            return true;
        }
        else
        {
            qDebug() << "删除学生失败:未找到ID为" << id << "的学生";
            return false;
        }
    }
    else
    {
        qDebug() << "删除学生失败:" << query.lastError().text();
        return false;
    }
}

/**
 * @brief 更新学生信息
 * @param student 学生对象
 * @return 更新成功返回true,否则返回false
 */
bool StudentDAO::updateStudent(const Student &student)
{
    if (!m_db.isOpen())
    {
        qDebug() << "更新学生失败:数据库未连接";
        return false;
    }

    QSqlQuery query(m_db);
    query.prepare("UPDATE student SET name = :name WHERE id = :id");
    query.bindValue(":name", student.name());
    query.bindValue(":id", student.id());

    if (query.exec())
    {
        if (query.numRowsAffected() > 0)
        {
            qDebug() << "更新学生成功:ID=" << student.id() << ", 新姓名=" << student.name();
            return true;
        }
        else
        {
            qDebug() << "更新学生失败:未找到ID为" << student.id() << "的学生";
            return false;
        }
    }
    else
    {
        qDebug() << "更新学生失败:" << query.lastError().text();
        return false;
    }
}

/**
 * @brief 根据ID查询学生
 * @param id 学生ID
 * @return 学生对象,如果不存在返回空对象
 */
Student StudentDAO::getStudentById(int id)
{
    Student student;

    if (!m_db.isOpen())
    {
        qDebug() << "查询学生失败:数据库未连接";
        return student;
    }

    QSqlQuery query(m_db);
    query.prepare("SELECT id, name FROM student WHERE id = :id");
    query.bindValue(":id", id);

    if (query.exec() && query.next())
    {
        student.setId(query.value(0).toInt());
        student.setName(query.value(1).toString());
        qDebug() << "查询学生成功:ID=" << student.id() << ", 姓名=" << student.name();
    }
    else
    {
        qDebug() << "查询学生失败:未找到ID为" << id << "的学生";
    }

    return student;
}

/**
 * @brief 查询所有学生
 * @return 学生对象列表
 */
QList<Student> StudentDAO::getAllStudents()
{
    QList<Student> students;

    if (!m_db.isOpen())
    {
        qDebug() << "查询所有学生失败:数据库未连接";
        return students;
    }

    QSqlQuery query("SELECT id, name FROM student", m_db);
    while (query.next())
    {
        Student student;
        student.setId(query.value(0).toInt());
        student.setName(query.value(1).toString());
        students.append(student);
    }

    qDebug() << "查询所有学生成功,共" << students.size() << "条记录";
    return students;
}