QT 操作SQL

news2024/11/28 14:28:24

目录

一、QT SQL简介

(一)、QT SQL对数据库支持

1、驱动层 

2、SQL API层

3、用户接口层

(二)SQLite数据库初识

1、第一步:在项目管理文件(.pro)中增加数据库模块​编辑

2、第二步:查看QT 对数据库的驱动的类型的支持

3、第三步:连接和打开数据库

4、第四步: 访问数据库

5、第五步:关闭数据库

(三)QtSqlite数据库接口介绍和使用

1、QSqlDataBase

2、QSqlQuery

3、数据库中的数据操作 (增查更删、显示UI上)

二、QT SQL案例:案例描述  数据在控件 QListWidget 展示和操作

(一)设计数据库

(二)涉及知识点

(三)QListWIdget 列表条目控件

1、界面建立

2、数据库操作代码

三、数据库模型高级接口 QSqlQueryModel使用和改进

(一)功能:Read-only data model for SQL result sets

知识点一:QSqlQueryModel模型基本使用

知识点二:QSqlQureyModel可编辑接口重写

知识点三:自定义接口函数

(二)QSqlQueryModel自定义高级接口应用:


一、QT SQL简介

应用程序操作数据库,需要数据库驱动,如:SQLITE,MySQL... ...

(一)、QT SQL对数据库支持

        在QT中,QT 为SQL数据库提供支持的基本模块。Qt SQL的API分为不同层:

1、驱动层 

 驱动层  对于QT是基于C++来实现的框架,该层主要包括QSqlDriverQSqlDriverCreator、QSqlDriverCreatorbase、QSqlDriverPlugin and QSqlResult。这一层提供了特定数据库和SQL API层之间的底层桥梁。

2、SQL API层

SQL API层  对于SQL API 层提供了数据库的访问相关类,其中,QSqlDataBase类进行连接,QSqlQuery完成数据库的交互。除此之外,还有QSqlError、QSqlField、QSqlIndex and QSqlRecord类。

3、用户接口层

用户接口层  用户接口层的几个类实现将数据库中的数据链接到窗口部件上,这些类是使用模型/视图框架实现的,他们是更高层次的抽象,主要包括QSqlQureyModel,QSqlTableModel and QSqlRelationalTableModel。

(二)SQLite数据库初识

对于数据库操作流程主要分为:

  • 第一步:在项目管理文件(.pro)中增加数据库模块
  • 第二步:查看QT 对数据库的驱动的类型的支持
  • 第三步:连接和打开数据库
  • 第四步:访问数据库
  • 第五步:关闭数据库

1、第一步:在项目管理文件(.pro)中增加数据库模块

2、第二步:查看QT 对数据库的驱动的类型的支持

显示支持的数据库驱动,MySql在QT中不直接支持,可通过以下几种方式:

  • ODBC连接Qt连接MySQL数据库最详细的教程_qt mysql_joey小天使的博客-CSDN博客、
  • MySQL Community ServerQt零基础系列10:windows 环境下如何添加MYSQL数据库驱动(补充内容) - 知乎 (zhihu.com)
  • 下载驱动QMYSQL driver

3、第三步:连接和打开数据库

4、第四步: 访问数据库

5、第五步:关闭数据库

db.close();

(三)QtSqlite数据库接口介绍和使用

表1 模块包含的主要类的功能

 Qt SQL采用的是MVC设计思想来处理数据,现对其主要类进行说明

1、QSqlDataBase

        QSqlDataBase用于建立与数据库的连接,在建立连接时,加载数据库驱动的时候,可以设置数据库类型和数据库名字。除此之外,还可以通过接口设置数据数据库名字、主机名、用户名和密码,其主要接口说明见表2。

 表2 QSqlDatabase操作主要接口

2、QSqlQuery

        QSqlQuery执行各种SQL语句的类,在打开成功连接的数据库后,则可以通过QsqlQuery的接口来访问数据库中的内容,其主要接口说明如下表3。

 表3 QSqlQuery操作主要接口

  •    数据库图形工具使用——SQLite Expert Professional 5

3、数据库中的数据操作 (增查更删、显示UI上)

(1)插入和查询

  • 插入操作语法:

  • 查询操作语法:

  • 如果想要查询所以的字段内容,可以采用:select * from 表名

 (2)更新和删除

  • 更新的操作语法

  • 删除的操作语法

  •  显示在UI上:利用查询功能


二、QT SQL案例:案例描述  数据在控件 QListWidget 展示和操作

(一)设计数据库

利用 qt 数据库,创建一个公司数据库(company. db),在该表中,创建一个员工表 (employee),员工主要包括:用户名和密码 都使用字符串类型。自己设计一个数据库用来存储公司员工的信息,并且可以通过界面来完成操作

数据库:company. db
员工表:staff
字段名有 id name age address salary

(二)涉及知识点

  • 知识点一:UI界面设计一个QListWIdget
  • 知识点二:sqlite数据生成
  • 知识点三:sqlite数据UI联动

(三)QListWIdget 列表条目控件

1、界面建立

建立mainwindow.ui是主界面和itemfrom.ui 是条目界面

 图1 项目文件 图2 条目界面新建过程(项目右键-->Add New)

图3 mainwindow.ui 主界面及其相关命名

 图4 itemfrom.ui 条目界面及label命名

2、数据库操作代码

 (添加、更新、删除、查询按钮需要跳转到槽)

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include"itemfrom.h"
#include<QListWidgetItem>

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

    //1、根据数据库类型  连接数据库
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("company.db");

    //2、打开数据库
    if(!db.open())
    {
        qDebug()<<"open error"<<db.lastError();
    }

    //3、根据需求  创建数据库中所需要的表
    QSqlQuery query;

    //员工表:staff
    //字段名有 id name age address salary
#if 0
    QString sqlCreateTable = QString("create table staff(id integer primary key autoincrement,"
                                     "name varchar(20),"
                                     "age int,"
                                     "address varchar(50),"
                                     "salary int);");
    if(!query.exec(sqlCreateTable))
    {
        qDebug()<<"create table error"<<db.lastError();
    }
    //插入
    QString sqlInsert = QString("insert into staff(name,age,address,salary) "
                                "values('张三',20,'广州天河区','12000');");
    if(!query.exec(sqlInsert))
    {
        qDebug()<<"insert table error"<<db.lastError();
    }
#endif

}

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


void MainWindow::on_btnAdd_clicked()
{
    //[1] 获取UI控件上的内容
    QString name = ui->lineEdit_name->text();
    QString age = ui-> lineEdit_age->text();
    QString address = ui->lineEdit_address->text();
    QString salary = ui->lineEdit_salary->text();

    //[2] 通过数据库接口的访问,将数据插入到数据库中
    QSqlQuery query;
    QString sqlInsert = QString("insert into staff(name,age,address,salary) "
                                "values('%1',%2,'%3',%4);").arg(name)
                                 .arg(age.toInt())
                                 .arg(address)
                                 .arg(salary.toInt());//查询数据库数据
    if(!query.exec(sqlInsert))
    {
        qDebug()<<"insert table error"<<db.lastError();
    }
}

void MainWindow::on_btnUpdate_clicked()
{
    ui->listWidget->clear();
    QSqlQuery query;

    QString id = ui->lineEdit_ID->text();
    QString name = ui->lineEdit_name->text();
    QString age = ui-> lineEdit_age->text();
    QString address = ui->lineEdit_address->text();
    QString salary = ui->lineEdit_salary->text();

    QString sqlUpdate_name = QString("update staff set name = '%1' where id = %2;").arg(name).arg(id.toInt());//查询数据库数据
    if(!query.exec(sqlUpdate_name))
    {
        qDebug()<<"update_name table error"<<db.lastError();
    }

//    QString sqlUpdate_age = QString("update staff set age = '%1' where id = %2;").arg(age.toInt()).arg(id.toInt());//查询数据库数据
//    if(!query.exec(sqlUpdate_age))
//    {
//        qDebug()<<"update_age table error"<<db.lastError();
//    }

//    QString sqlUpdate_address = QString("update staff set address = '%1' where id = %2;").arg(address).arg(id.toInt());//查询数据库数据
//    if(!query.exec(sqlUpdate_address))
//    {
//        qDebug()<<"update_address table error"<<db.lastError();
//    }

//    QString sqlUpdate_salary = QString("update staff set salary = '%1' where id = %2;").arg(salary.toInt()).arg(id.toInt());//查询数据库数据
//    if(!query.exec(sqlUpdate_salary))
//    {
//        qDebug()<<"update_salary table error"<<db.lastError();
//    }
}


void MainWindow::on_btnDelete_clicked()
{
    //[1]删除数据库中的记录
    QSqlQuery query;
    int id = ui->lineEdit_ID->text().toInt();
    QString sqlDelete = QString("delete from staff where id = %1;").arg(id);//查询数据库数据
    if(!query.exec(sqlDelete))
    {
        qDebug()<<"delete table error"<<db.lastError();
    }

    //[2]同时删除UI控件上的内容,下标从0开始
    ui->listWidget->takeItem(id-1);
}

void MainWindow::on_btnSearch_clicked()
{ 
    ui->listWidget->clear();//在查询数据之前,将列表中的数据清空

    QSqlQuery query;
    //[1]向数据库 下达查询数据的命令
    QString sqlSelect = QString("select * from staff;");//查询数据库数据
    if(!query.exec(sqlSelect))
    {
        qDebug()<<"select table error"<<db.lastError();
    }

    //[2]遍历数据库记录
    while(query.next())
    {
        int id = query.value("id").toInt();
        QString name = query.value("name").toString();
        int age = query.value("age").toInt();
        QString address = query.value("address").toString();
        int salary = query.value("salary").toInt();

        qDebug()<<"id = "<<id<<"  name = "<<name<<"  age = "<<age<<"  address = "<<address<<"  salary = "<<salary;

        //[3]每遍历一条记录,就要更新到UI控件上
        //[3.1]创建一个列表条目
        itemFrom* staffitem = new itemFrom;//new一个自定义的条目控件staffitem
        staffitem->setStaffInfo(id,name,age,address,salary);

        QListWidgetItem* item = new QListWidgetItem;//new一个listWidget的条目item

        int w = staffitem->width();
        int h = staffitem->height();
        item->setSizeHint(QSize(w,h));//将item的宽高 与自定义的条目staffitem大小设置一致

        ui->listWidget->addItem(item);//将item增加到listWidget上
        ui->listWidget->setItemWidget(item,staffitem);//再给item设置 对应控件条目staffitem

    }

}

三、数据库模型高级接口 QSqlQueryModel使用和改进

(一)功能:Read-only data model for SQL result sets

以只读模型方式来访问数据库,将得到询问结果集

解释:以只读访问查询数据库数据,并把数据存放在一个结果集,数据不能修改,如果想要修改,必须进行其他操作(重写虚函数)。

知识点一:QSqlQueryModel模型基本使用

 //使用QSqlQueryModel
    //[1]创建QSqlQueryModel对象,并设置相关的表头信息
    QSqlQueryModel *model=new QSqlQueryModel;

    //执行sql语句    //将查询的结果转换成 model对象
    model->setQuery("select name,age,address,salary from staff");
    //根据需求设置表头信息
    model->setHeaderData(0,Qt::Horizontal,tr("Name"));
    model->setHeaderData(1,Qt::Horizontal,tr("Age"));
    model->setHeaderData(2,Qt::Horizontal,tr("Address"));
    model->setHeaderData(3,Qt::Horizontal,tr("Salary"));

    //[2]给ui控件设置一个模型
    QTableView *view = new QTableView(ui->centralwidget);

    view->setFixedSize(QSize(this->width(),this->height()));
    view->setModel(model);//相当于将数据联动 UI控件上

    //将view 显示出来
    view->show();

知识点二:QSqlQureyModel可编辑接口重写

默认情况下是只读,要使得可读可写,必须创建子类并且重写setData()和flags()函数。另外一个选择是QSqlTableModel,它提供基于简单database表的可读可写模型。

1、接口一:

[virtual]​​​​​​​ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)

2、接口二:
[override virtual] Qt::ItemFlags flags(const QModelIndex &index) const​​​​​​​

editquerymodel.cpp

#include "editquerymodel.h"
#include<QSqlQuery>

editQueryModel::editQueryModel()
{
    
}

bool editQueryModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    //[1]判断列是否为有效的列  员工---Id 用户名 年龄 地址 薪资
    if(index.column() < 1 ||index.column() > 4)
    return false;
    
    //获取列所对应的id
    QModelIndex primaryIndex= QSqlQueryModel::index(index.row(),0);
    int id = this->data(primaryIndex).toInt();//获取字段表中的id
    
    //在修改行之前,将数据清除,将整个model清空
    this->clear();
    bool ok;
    //根据需求修改对应的列
    if(index.column() ==1)//用户名对应第一列
    {
        ok = setName(id,value.toString());
    }
    
    //刷新数据
    refresh();
    return ok;
}

Qt::ItemFlags editQueryModel::flags(const QModelIndex &index) const
{
    //[1]获取当前单元格的编辑状态
    Qt::ItemFlags flag = QSqlQueryModel::flags(index);
    
    //[2]给现有的标志增加可编辑的标志
    flag = flag | Qt::ItemIsEditable;//给它设置一个可编辑的状态
    return flag;
    
}

void editQueryModel::refresh()
{
    //执行查询   将数据库的数据查询出来,转换成一个model
    this->setQuery("select * from staff");
    this->setHeaderData(0,Qt::Horizontal,"Name");
    
}

bool editQueryModel::setName(int useId, const QString &name)
{
    //执行name的更新
    QSqlQuery query;
    query.prepare("update staff set name = ? where id = ?");
    
    query.addBindValue(name);
    query.addBindValue(useId);
    return query.exec();
}

editquerymodel.h

#ifndef EDITQUERYMODEL_H
#define EDITQUERYMODEL_H

#include<QSqlQueryModel>

class editQueryModel : public QSqlQueryModel
{
public:
    editQueryModel();
    
    //重写基类的虚函数
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);//操作数据库
    Qt::ItemFlags flags(const QModelIndex &index) const;//给一个单元框属性 可编辑的状态
    
private:
    //自定义接口函数
    //更新数据
    void refresh();
    
    //根据需求来定义修改表中的内容的接口
    bool setName(int useId,const QString& name);
    
};

#endif // EDITQUERYMODEL_H

知识点三:自定义接口函数

refresh()、setName()

(二)QSqlQueryModel自定义高级接口应用:

1、案例描述

        通过重写QSqlQueryModel虚函数,实现对QSqlQueryModel的改造,让改造后的editquerymodel实现可读可写。下列函数editquerymodel实现了对第1列name的修改,并通过QTableView控件来实现staff表格的展示。

2、案例实现

1)新建mainwindow项目

2)新建c++ class:项目右键--->Add New...--->c++--->c++ class

(生成 editquerymodel.cpp​​​​​​​、editquerymodel.h两个文件)

3)在.pro文件中增加sql

 4)editquerymodel.h接口类的声明

#ifndef EDITQUERYMODEL_H
#define EDITQUERYMODEL_H

#include<QSqlQueryModel>

class editQueryModel : public QSqlQueryModel
{
public:
    editQueryModel();

    //重写基类的虚函数
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);//操作数据库
    Qt::ItemFlags flags(const QModelIndex &index) const;//给一个单元框属性 可编辑的状态

private:
    //自定义接口函数
    //更新数据
    void refresh();

    //根据需求来定义修改表中的内容的接口
    bool setName(int useId,const QString& name);

};

#endif // EDITQUERYMODEL_H

5)editquerymodel.cpp接口类的实现

#include "editquerymodel.h"
#include<QSqlQuery>

editQueryModel::editQueryModel()
{

}

bool editQueryModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    //[1]判断列是否为有效的列  员工---Id 用户名 年龄 地址 薪资
    if(index.column() < 1 ||index.column() > 4)
    return false;

    //获取列所对应的id
    QModelIndex primaryIndex= QSqlQueryModel::index(index.row(),0);
    int id = this->data(primaryIndex).toInt();//获取字段表中的id

    //在修改行之前,将数据清除,将整个model清空
    this->clear();
    bool ok;
    //根据需求修改对应的列
    if(index.column() ==1)//用户名对应第一列
    {
        ok = setName(id,value.toString());
    }

    //刷新数据
    refresh();
    return ok;
}

Qt::ItemFlags editQueryModel::flags(const QModelIndex &index) const
{
    //[1]获取当前单元格的编辑状态
    Qt::ItemFlags flag = QSqlQueryModel::flags(index);

    //[2]给现有的标志增加可编辑的标志
    if(index.column()==1)//当是第一列的时候
    {
        flag = flag | Qt::ItemIsEditable;//给它设置一个可编辑的状态
        return flag;
    }
}

void editQueryModel::refresh()
{
    //执行查询   将数据库的数据查询出来,转换成一个model
    this->setQuery("select * from staff");
    this->setHeaderData(0,Qt::Horizontal,"ID");
    this->setHeaderData(1,Qt::Horizontal,"Name");
    this->setHeaderData(2,Qt::Horizontal,"Age");
    this->setHeaderData(3,Qt::Horizontal,"Address");
    this->setHeaderData(4,Qt::Horizontal,"Salary");
}

bool editQueryModel::setName(int useId, const QString &name)
{
    //执行name的更新,相当于刷新接口
    QSqlQuery query;
    query.prepare("update staff set name = ? where id = ?");

    query.addBindValue(name);
    query.addBindValue(useId);
    return query.exec();
}

6)mainwindow.h 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QSqlDatabase>
#include<QSqlQueryModel>
#include<QSqlError>
#include<QtDebug>
#include<QSqlQuery>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
    QSqlDatabase m_db;
};
#endif // MAINWINDOW_H

7)mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<editquerymodel.h>
#include<QTableView>

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

    m_db = QSqlDatabase::addDatabase("QSQLITE");
    m_db.setDatabaseName("compary.db");

    if(!m_db.open())
    {
        qDebug()<<"open error"<<m_db.lastError();
    }

    QSqlQuery query;
#if 0
    QString sqlCreatTable = QString("create table staff(id integer primary key autoincrement,"
                                    "name varchar(20),"
                                    "age int,"
                                    "address varchar(50),"
                                    "salary int);");
    if(!query.exec(sqlCreatTable))
    {
        qDebug()<<"table create error"<<m_db.lastError();
    }

    //插入操作
    QString sqlInsert = QString("insert into staff(name,age,address,salary) "
                                "values('张三',20,'广州天河区','12000');");
    if(!query.exec(sqlInsert))
    {
        qDebug()<<"insert table error"<<m_db.lastError();
    }


#endif

    //[1]创建模型对象
    editQueryModel *model = new editQueryModel;
    model->setQuery("select * from staff");
    model->setHeaderData(0,Qt::Horizontal,"ID");
    model->setHeaderData(1,Qt::Horizontal,"Name");
    model->setHeaderData(2,Qt::Horizontal,"Age");
    model->setHeaderData(3,Qt::Horizontal,"Address");
    model->setHeaderData(4,Qt::Horizontal,"Salary");

    //[2]创建表格控件
    QTableView *view = new QTableView(ui->centralwidget);
    view->setFixedSize(QSize(this->width(),this->height()));
    view->setModel(model);
    view->show();
}

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

 四、总结

        本文通过学习QSqlDataBase、QSqlQuery、QSqlQueryModel等QT数据库接口,实现对数据库的基本操作、数据的UI控件显示,其中UI控件使用了QListWidget、QTableView,控件的异同请参考博客:QTableView、QTreeView、QListWIdget相同点和区别(异同)_qtreeview与qtreewidget的区别_三公子Tjq的博客-CSDN博客

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

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

相关文章

用讯飞星火大模型1分钟写一个精美的PPT

文章目录 前言SparkDesk讯飞星火认知大模型简介利用讯飞星火写一个转正述职ppt1.告诉讯飞星火我想写一篇转正述职ppt2.利用MindShow一键生成ppt 申请体验写在最后 前言 随着ChatGPT迅速走红,国内各大企业纷纷发力认知大模型领域。经过一段时间的酝酿,讯飞“星火认知大模型”于…

家门口可以参加公益小天使活动啦

“我的布娃娃可以换你的书吗&#xff1f;” “发现有人晕倒&#xff0c;第1步要确认环境安全。” 这是5月14日上午&#xff0c;在武昌区水果湖街道滨湖社区&#xff0c;闲置互换应急科普活动上发生的对话 该活动由水果湖街道滨湖社区和武汉公益小天使联合发起。5月初&#x…

出现找不到msvcp140.dll无法继续执行代码要怎么解决?

出现找不到msvcp140.dll无法继续执行代码要怎么解决&#xff1f;当你尝试在Windows系统上运行某些程序或游戏时&#xff0c;可能会遇到“找不到msvcp140.dll无法继续执行代码”的错误提示。这个错误通常表示你的系统缺少了msvcp140.dll文件&#xff0c;而这个文件是Visual C Re…

SQL server 纵横报表查询

select warehouseid AS 仓库, case when Udf2 SAP THEN SAP WHEN Udf2 SNC THEN SNC ELSE 手工创建 end AS 创建来源 ,COUNT(isnull(UDF2,手工创建)) AS 数量 from DOC_Appointment_Header dah where convert(varchar(10),AddTime,120) > 2022-09-01 --and warehousei…

ASEMI代理ADI亚德诺ADP5054ACPZ-R7供电管理芯片介绍

编辑-Z 本文主要介绍ADP5054ACPZ-R7供电管理芯片的基本特性和应用场景。该芯片支持多路输出&#xff0c;具有高效和可靠性的特点&#xff0c;适用于各种电力系统和工业控制设备。 1、ADP5054ACPZ-R7的基本特性 ADP5054ACPZ-R7是一款高度集成的供电管理芯片&#xff0c;具有以…

python argparse 模块命令行参数解析

1.概述 argparse 是 python 的一个命令行解析包&#xff0c;可根据需要编写高可读性的程序。本文针对项目中对 argparse 的用法&#xff0c;用实例对各个参数进行讲解&#xff0c;力求达到让读者秒懂的目的。 2.api概述 2.1 ArgumentParser 对象 class argparse.ArgumentPar…

msvcr120.dll丢失怎样修复?msvcr120.dll丢失修复的四个方法

打开软件跟游戏提示msvcr120.dll丢失&#xff0c;无法执行此代码怎么办&#xff1f;刚刚遇到这个问题&#xff0c;我都无从下手。家人们&#xff0c;你是不是也被这个问题也困扰过。msvcr120.dll是什么文件呢&#xff1f;经过我一个下午的时间研究&#xff0c;终于搞清楚了&…

在 Mac 上的“终端”中执行.out文件

在 Mac 上的“终端”中执行.out文件 安装C及设置C语言环境怎么运行 安装C及设置C语言环境 最近在自学C语言&#xff0c;因为用的是mac电脑&#xff08;MacBook Air M1)&#xff0c;自带了C语言环境&#xff0c;如果用的是windows系统&#xff0c;可能这篇文章对您没有一点帮助…

10年软件测试人劝你千万别上当,测试岗位就是个巨坑......

每次都有人问我软件测试的前景是什么样的&#xff0c;每年也会有人很多人纷纷涌入测试的岗位上&#xff0c;希望自己能够进入阿里、华为等大厂。 但是测试岗位真的那么吃香吗&#xff1f;今天我结合从零基础小白到测试开发的成长经历&#xff0c;来说下这个行业的发展前景&…

基于改进MRAS算法的永磁同步电机参数辨识

基于改进MRAS算法的永磁同步电机参数辨识 摘 要永磁同步点电机参数辨识算法介绍永磁同步电机数学模型改进MRAS参数辨识算法递推最小二乘法辨识原理递推最小二乘法结合MRAS算法原理仿真结果分析总结 摘 要 在永磁同步电机运行时&#xff0c;电机的电气参数会受到温度以及磁链饱…

KDZD400Q便携式三氯乙烯浓度检测仪

一、产品概述 检测仪用于快速检测多种气体浓度、温湿度测量并超标报警的场合。采用2.31寸高清彩屏实时显示&#xff0c;选用进口品牌的气体传感器&#xff0c;主要检测原理有&#xff1a;电化学、红外、催化燃烧、热导、PID 光离子等。 可以检测管道中或受限空间、大气环境中的…

领英的大败退,是对本土化的深刻误解

领英似乎还没思考清楚&#xff0c;本土化到底意味着什么&#xff1f; 2023年5月9日&#xff0c;领英宣布本土化求职平台领英职场将在8月9日停止服务。据了解&#xff0c;领英职场于去年12月14日上线&#xff0c;上线不到半年就将下线&#xff0c;比领英之前推出的赤兔更“短命…

Java【网络原理1】什么是 TCP/IP 五层模型? 数据传输的封装和分用?

文章目录 前言一、网络协议分层二、数据的网络传输1, 封装2, 分用3, 实际情况 总结 前言 &#x1f4d5;各位读者好, 我是小陈, 这是我的个人主页 &#x1f4d7;小陈还在持续努力学习编程, 努力通过博客输出所学知识 &#x1f4d8;如果本篇对你有帮助, 烦请点赞关注支持一波, 感…

文本三剑客:sed编辑器

sed编辑器 sed是一种流编辑器&#xff0c;流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。sed编辑器可以根据命令来处理数据流中的数据&#xff0c;这些命令要么从命令行中输入&#xff0c;要么存储在一个命令文本文件中。 工作流程 sed 的工作流程主要…

Python时间模块:time和datetime的区别与用法

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 目录标题 前言一. Python中表示时间的两种方式&#xff1a;二. time三. datetime1. datetime.datetime2.datetime.timedelta 尾语 &#x1f49d; 一. Python中表示时间的两种方式&#xff1a; 时间戳&#xff1a;相对于197…

Java PECS(Producer Extends Consumer Super)原则

在看 Alibaba 开发手册时遇到 PECS 原则&#xff0c;刚开始阅读时感觉比较绕&#xff0c;也搜索了一些博文参考&#xff0c;个人觉得 Stackoverflow 的这篇文章比较实用 —— What is PECS (Producer Extends Consumer Super)? 后面结合 JDK 源码梳理了下 // java/util/List…

电脑压缩包文件不见了怎么办?2种办法轻松找回电脑丢失文件!

一般情况下&#xff0c;为了节省磁盘空间或者传送文件时能够更快点&#xff0c;我们都会选择把文件进行压缩&#xff0c;这样会更加方便。 但时间一长&#xff0c;由于各种各样的原因&#xff0c;比如&#xff1a; 清理积累下来的压缩包时不小心把需要的压缩文件删除了&#x…

Angular与PDF之三: 服务器端渲染PDF

一、Angular PDf server 端渲染 1. 环境准备 _ _ ____ _ ___/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|/ △ \ | _ \ / _ | | | | |/ _ | __| | | | | | | / ___ \| | | | (_| | |_| | | (_| | | | |___|…

RK 平台MIPI 点屏注意事项

转自&#xff1a;https://www.cnblogs.com/chorm590/p/11658360.html rk 平台关于 MIPI 屏幕的点屏流程已经非常完善了&#xff0c;基本上只要确定了硬件没问题、接线没问题、屏幕没问题&#xff0c;再稍稍配置一下 dtsi 里的参数就可以的了。 MIPI 点屏流程大致可以概括为以下…

一步一步教你写kubernetes sidecar

什么是sidecar&#xff1f; sidecar&#xff0c;直译为边车。 如上图所示&#xff0c;边车就是加装在摩托车旁来达到拓展功能的目的&#xff0c;比如行驶更加稳定&#xff0c;可以拉更多的人和货物&#xff0c;坐在边车上的人可以给驾驶员指路等。边车模式通过给应用服务加装一…