QT数据库SQLite:QsqlTableModel使用总结

news2025/1/18 6:20:47

数据库连接、数据模型与界面组件所涉及的类之间的关系如下所示:

数据库类

QSqlDatabase 类用于建立与数据库的连接,QSqlDatabase 对象就表示这种连接。QSqlDatabase 类的功能主要分为三大部分:

1、创建数据库连接,即创建 QSqlDatabase 对象,加载指定类型的数据库驱动。

静态函数 QSqlDatabase::addDatabase()创建 QSqlDatabase 对象:

QSqlDatabase QSqlDatabase::addDatabase(const QString &type,

const QString &connectionName = QLatin1String(defaultConnection))

参数 type 是要连接的数据库类型:

如“QSQLITE”就是指 SQLite 数据库,参数 connectionName 是所创建的数据库连接的名称,如

果不设置这个参数,就采用应用程序默认的数据库连接。使用函数 addDatabase()创建 QSqlDatabase 对象时只是设置了驱动程序名称,设置的 connection Name 会被自动添加到应用程序的数据库连接名称列表。如果成功创建 QSqlDatabase 对象,QSqlDatabase 的函数 isValid()会返回 true。一个 QSqlDatabase 对象用于表示一个数据库连接,一个应用程序里可以创建多个 QSqlDatabase 对象,它们可分别连接一个数据库。使用静态函数 QSqlDatabase::connectionNames()返回应用程序里所有已 创建的数据库连接名称列表。如果一个应用程序里有多个数据库连接,可以使用静态函数 QSqlDatabase::database()通过 connectionName 来引用其中的某个数据库连接。

2、打开数据库,设置需要连接的数据库具体参数,例如数据库名称、用户名、用户密码等,

然后打开数据库。只有打开数据库之后,才可以进行数据查询和修改等操作。

运行函数 QSqlDatabase::addDatabase()只是加载了数据库驱动,创建了数据 库连接,还需要用 QSqlDatabase 的函数 open()打开一个具体的数据库。设置好连接数据库参数后,用函数 open()打开数据库,如果 open()的返回值为 true,表示成功打开数据库。若要关闭数据库,则要使用函数 close()。

3、对数据库进行事务(transaction)操作,获取数据库的一些信息。

bool MainWindow::openDatabase(QString aFile)
{
    DB=QSqlDatabase::addDatabase("QSQLITE","Database1");	//添加 SQLITE数据库驱动
    DB.setDatabaseName(aFile);	//设置数据库名称
    if (!DB.open())     //打开数据库失败
        return false;
    else
    {
        openTable();	//打开数据表
        return true;
    }
}

QSqlTableModel 是一个模型类,它与数据库中的一个数据表关联后就作为该数据表的模型。

QSqlTableModel 类的构造函数定义如下:

QSqlTableModel(QObject *parent = nullptr, const QSqlDatabase &db = QSqlDatabase())

创建 QSqlTableModel 对象时需要指定数据库连接,也就是设置一个 QSqlDatabase 对象。如果

不指定数据库连接,就使用应用程序的默认数据库连接。还需要使用 QSqlTableModel 的 setTable()函数设置需要连接的数据表。

函数 select()。这个函数的作用是根据当前设置的排序和过滤规则从数据表查询数据并将 其刷新到数据模型。在使用函数 setTable()设置数据表之后,还需要运行函数 select()才能将数据刷 新到模型。函数 select()的返回值若为 true,则表示数据查询操作成功;若为 false,则表示操作失 败,可以通过函数 lastError()获取错误信息。

    tabModel=new QSqlTableModel(this,DB);	//数据模型
    tabModel->setTable("employee");			//设置数据表
    tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);	//数据保存方式,OnManualSubmit , OnRowChange
    tabModel->setSort(tabModel->fieldIndex("empNo"),Qt::AscendingOrder); //排序
    if (!(tabModel->select()))	//查询数据失败
    {
        QMessageBox::critical(this, "错误信息",
                              "打开数据表错误,错误信息:\n"+tabModel->lastError().text());
        return;
    }

建立View组件与model的模型/视图

为一个 QTableView 组件设置一个 QSqlTableModel 模型后,它们就组成模型/视图结构,可以

显示和编辑数据表的数据。还可以为 QSqlTableModel 模型设置一个 QItemSelectionModel 对象作

为选择模型。在 QTableView 组件中可以使用自定义代理。

    //Model/View结构
    ui->tableView->setModel(tabModel);	//设置数据模型
    selModel=new QItemSelectionModel(tabModel,this);		//关联选择模型
    ui->tableView->setSelectionModel(selModel); //设置选择模型

建立界面组件与Model的映射

QDataWidgetMapper 类对象要设置一个 QSqlTableModel 模型,然后将数据表的某个字段与界面

上某个组件建立映射,界面组件就可以自动显示这个字段的数据,成为数据感知(data-aware)组件。这样这些界面组件就会自动显示关联字段的数据,并且在组件中修改数据后可以提交到模型。

一般的数值、字符串、备注等类型的字段可以用 QSpinBox、QLineEdit、QPlainTextEdit 等界

面组件作为数据感知组件,但是 BLOB 类型的字段不能直接与某个界面组件建立映射。如图片数据信息,需要单独编写代码实现图片的显示、导入和清除等操作。

QDataWidgetMapper::AutoSubmit:自动提交。当一个界面组件失去输入焦点时,所进行的

修改自动提交到模型。

QDataWidgetMapper 对象指向数据模型的某一行记录并将其作为当前行,函数 currentIndex()

返回当前行号,函数 setCurrentIndex()可以设置当前行号,toFirst()、toPrevious()、toNext()和 toLast() 函数可以移动当前行。QDataWidgetMapper 对象的当前行变化时,设置了映射字段的界面组件会 自动更新显示当前记录的数据

    //创建界面组件与数据模型的字段之间的数据映射
    dataMapper= new QDataWidgetMapper(this);
    dataMapper->setModel(tabModel);		//设置数据模型
    dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit); //数据更新方式
    //界面组件与数据模型的具体字段之间的联系
    dataMapper->addMapping(ui->dbSpinEmpNo,tabModel->fieldIndex("empNo"));
    dataMapper->addMapping(ui->dbEditName,tabModel->fieldIndex("Name"));
    dataMapper->addMapping(ui->dbComboSex,tabModel->fieldIndex("Gender"));
    dataMapper->addMapping(ui->dbEditBirth,tabModel->fieldIndex("Birthday"));
    dataMapper->addMapping(ui->dbComboProvince,tabModel->fieldIndex("Province"));
    dataMapper->addMapping(ui->dbComboDep,tabModel->fieldIndex("Department"));
    dataMapper->addMapping(ui->dbSpinSalary,tabModel->fieldIndex("Salary"));
    dataMapper->addMapping(ui->dbEditMemo,tabModel->fieldIndex("Memo"));
    dataMapper->toFirst();  //移动到首记录

界面的数据表格上点击 单元格,使数据模型 tabModel 的当前记录发生变化时,dataMapper 的当前行并不会自动变化。因此如果要确保视图组件 tableView 中的当前行和数据映射对象 dataMapper 的当前行是一致,在修改currentIndex发生变化时候,需要使用以下来更新

dataMapper->setCurrentIndex(current.row()); //更新数据映射的行号

设置字段显示的标题

函数 fieldIndex()。这个函数根据字段名称返回字段的序号。若字段不存在,则返回-1。使用时注意要与数据库的表格字段一致,以防找不到字段

函数 setHeaderData()。这个函数用于设置一个字段的表头数据,一般用于设置字段的显示标题。

bool QSqlQueryModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole)

其中,section 是字段序号;orientation 是方向,对于字段就是 Qt::Horizontal;value 是需要设置的数据;role 是数据的角色,默认为 Qt::EditRole。如果不进行表头设置,在 QTableView 组件里显示表格数据时,会将字段名作为表头。

    tabModel->setHeaderData(tabModel->fieldIndex("empNo"),  Qt::Horizontal, "工号");
    tabModel->setHeaderData(tabModel->fieldIndex("Name"),   Qt::Horizontal, "姓名");
    tabModel->setHeaderData(tabModel->fieldIndex("Gender"), Qt::Horizontal, "性别");
    tabModel->setHeaderData(tabModel->fieldIndex("Birthday"),   Qt::Horizontal, "出生日期");
    tabModel->setHeaderData(tabModel->fieldIndex("Province"),   Qt::Horizontal, "省份");
    tabModel->setHeaderData(tabModel->fieldIndex("Department"), Qt::Horizontal, "部门");
    tabModel->setHeaderData(tabModel->fieldIndex("Salary"), Qt::Horizontal, "工资");
    tabModel->setHeaderData(tabModel->fieldIndex("Memo"),Qt::Horizontal,"备注");
    tabModel->setHeaderData(tabModel->fieldIndex("Photo"),Qt::Horizontal,"照片");

获取记录的字段

QSqlRecord 类记录了数据表的字段信息和一条记录的数据内容,QSqlTableModel 有两种参数

形式的函数 record()可以返回一条记录。

QSqlRecord QSqlTableModel::record() //返回字段定义

QSqlRecord QSqlTableModel::record(int row) //返回字段定义和数据

不带有参数的函数 record()返回的一个 QSqlRecord 对象只有记录的字段定义,没有各字段的

数据,一般用于获取一个数据表的字段定义。带有参数的函数 record()返回行号为 row 的记录,包括记录的字段定义和数据。

//获取所有字段名称
void MainWindow::getFieldNames()
{
    QSqlRecord  emptyRec=tabModel->record();    //获取空记录,只有字段名
    for (int i=0;i<emptyRec.count();i++)
        ui->comboFields->addItem(emptyRec.fieldName(i));
}

添加-修改-插入-删除项

insertRecord() 用于添加或插入记录,函数 setRecord()用于修改记录,删除记录使用的是函数 removeRow()。

在插入记录时,即使是必填字段(例如 Name 字段)没有被赋值,程序也不会出错,因为我们设置的数据模型 tabModel 的编辑策略是 OnManualSubmit。但是在保存修改到数据库时,如果必填字段没有设置数据,则会出现错误。

void MainWindow::on_actRecAppend_triggered()
{//添加一条记录
     使用QSqlRecord
    QSqlRecord rec=tabModel->record();      //获取一个空记录,只有字段定义
    rec.setValue(tabModel->fieldIndex("empNo"),2000+tabModel->rowCount());
    rec.setValue(tabModel->fieldIndex("Gender"),"男");  //设置数据
    tabModel->insertRecord(tabModel->rowCount(),rec);   //插入到数据模型的最后

    selModel->clearSelection();
    QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1);     //创建最后一行的ModelIndex
    selModel->setCurrentIndex(curIndex,QItemSelectionModel::Select);

    showRecordCount();

    项数据模型操作方式,功能相同,但是不符合数据库的操作习惯
    //    tabModel->insertRow(tabModel->rowCount(),QModelIndex());    //在末尾添加一行
    //    QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1); //创建最后一行的ModelIndex
    //    theSelection->clearSelection();     //清空选择项
    //    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);    //设置刚插入的行为当前行

    //    int currow=curIndex.row();  //获得当前行编号
    //    tabModel->setData(tabModel->index(currow,tabModel->fieldIndex("empNo")),
    //                      2000+tabModel->rowCount());       //自动生成编号
    //    tabModel->setData(tabModel->index(currow,tabModel->fieldIndex("Gender")),"男");  //必填字段,需要赋值
    //    showRecordCount();

    // 插入行时设置缺省值,需要在primeInsert()信号里去处理
}


void MainWindow::on_actRecInsert_triggered()
{//插入一条记录
     使用QSqlRecord
    QModelIndex curIndex=ui->tableView->currentIndex();
    QSqlRecord rec=tabModel->record();      //获取一个空记录,只有字段定义
    tabModel->insertRecord(curIndex.row(),rec);     //在当前行前面插入一条记录

    selModel->clearSelection();
    selModel->setCurrentIndex(curIndex,QItemSelectionModel::Select);    //设置当前行
    showRecordCount();

    //项数据模型操作方式,功能相同,但是不符合数据库的操作习惯
    //    QModelIndex curIndex=ui->tableView->currentIndex();     //当前行的模型索引
    //    tabModel->insertRow(curIndex.row(),QModelIndex());      //插入一行
    //    theSelection->clearSelection(); //清除已有选择
    //    theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);    //选择新插入的一行
    //    showRecordCount();

}


void MainWindow::on_actRecDelete_triggered()
{//删除当前记录
    QModelIndex curIndex=selModel->currentIndex();  //获取当前选择单元格的模型索引
    tabModel->removeRow(curIndex.row()); //删除当前行
    showRecordCount();
}

保存或取消修改

数据模型 tabModel 的编辑策略为 OnManualSubmit时,即手动提交 修改。当数据模型的数据被修改后,不管是直接修改字段值,还是插入或删除记录,在未提交修改前, tabModel->isDirty()函数都返回 true。保存会将所有对Model进行的增删改同步到数据库.db文件中,取消会撤销对model的增删改操作。

函数 submitAll()用于将数据模型所有未提交的修改保存到数据库,函数 revertAll()取消所有修

改。调用 submitAll()保存数据时如果失败,可以通过函数 lastError()获取错误的具体信息。

void MainWindow::on_actRevert_triggered()
{//取消修改
    tabModel->revertAll();
    ui->actSubmit->setEnabled(false);
    ui->actRevert->setEnabled(false);
    showRecordCount();
}

void MainWindow::on_actSubmit_triggered()
{//保存修改
    bool res=tabModel->submitAll();
    if (!res)
        QMessageBox::information(this, "消息", "数据保存错误,错误信息\n"+tabModel->lastError().text());
    else
    {
        ui->actSubmit->setEnabled(false);
        ui->actRevert->setEnabled(false);
    }
    showRecordCount();
}

遍历数据记录

获取model的count后,使用record(i)即可遍历每一条记录,通过value函数访问每个字段对应的数据,便可遍历修改后保存。

void MainWindow::on_actScan_triggered()
{//涨工资,记录遍历
    if (tabModel->rowCount()==0)
        return;

    for (int i=0;i<tabModel->rowCount();i++)
    {
        QSqlRecord aRec=tabModel->record(i); //获取一条记录
        float salary=aRec.value("Salary").toFloat();
        salary=salary*1.1;
        aRec.setValue("Salary",salary);     //更新记录数据
        tabModel->setRecord(i,aRec);        //更新记录
    }

    // 索引方式刷新记录,速度一样
    //    float   salary;
    //    for (int i=0;i<tabModel->rowCount();i++)
    //    {
    //        salary=tabModel->data(tabModel->index(i,10)).toFloat();
    //        salary=salary*1.1;
    //        tabModel->setData(tabModel->index(i,10),salary);
    //    }

    if (tabModel->submitAll())
        QMessageBox::information(this, "消息", "涨工资数据计算完毕");
}

记录排序

QSqlTableModel 模型里的记录可以按某个字段排序,对应 SQL 语句中的 ORDER BY 子句。

QSqlTableModel 有 setSort()和 sort()两个函数用于排序。

void QSqlTableModel::setSort(int column, Qt::SortOrder order) //设置排序条件

void QSqlTableModel::sort(int column, Qt::SortOrder order) //立刻排序

参数 column 表示排序字段的字段序号;参数 order 表示排序方式,可设置为升序(Qt::Ascending

Order)或降序(Qt::DescendingOrder)。

这两个函数稍有差别,函数 setSort()只是用于设置排序条件,需要再运行 select()函数才会刷

新数据模型的数据;函数 sort()则是用于根据设置的字段和排序方式直接排序并刷新数据模型,无

须调用 select()函数。

void MainWindow::on_comboFields_currentIndexChanged(int index)
{//选择字段进行排序
    if (ui->radioBtnAscend->isChecked())
        tabModel->setSort(index,Qt::AscendingOrder);
    else
        tabModel->setSort(index,Qt::DescendingOrder);

    tabModel->select();
}

void MainWindow::on_radioBtnAscend_clicked()
{//升序排序
    tabModel->setSort(ui->comboFields->currentIndex(),Qt::AscendingOrder);
    tabModel->select();     //setSort()之后需要执行select()才会刷新数据
}

void MainWindow::on_radioBtnDescend_clicked()
{//降序排序
    tabModel->sort(ui->comboFields->currentIndex(),Qt::DescendingOrder);
    //    tabModel->setSort(ui->comboFields->currentIndex(),Qt::DescendingOrder);
    //    tabModel->select();
}

记录过滤

QSqlTableModel 的 setFilter()函数可设置记录过滤条件,该函数原型定义如下:

void QSqlTableModel::setFilter(const QString &filter)

字符串类型的参数 filter 是过滤条件,实际上就是 SELECT 语句里 WHERE 子句的条件。

运行 setFilter()函数后无须调用 select()函数就可以立即刷新记录,若要取消过滤,只需在

setFilter()函数里传递一个空字符串。

void MainWindow::on_radioBtnMan_clicked()
{
    tabModel->setFilter(" Gender='男' ");
    showRecordCount();
}

void MainWindow::on_radioBtnWoman_clicked()
{
    tabModel->setFilter(" Gender='女' ");
    showRecordCount();
}

void MainWindow::on_radioBtnBoth_clicked()
{
    tabModel->setFilter("");
    showRecordCount();
}

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

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

相关文章

[MoeCTF 2022]what are y0u uploading?

[BJDCTF 2020]签个到? 解压后发现两个文件夹&#xff0c;进去发现有个压缩包 这里压缩包打不开&#xff0c;就直接给改成png后缀 发现变成了一个二维码 然后用QR工具扫一下 得到flag NSSCTF{i_am_a_tupian} [MoeCTF 2022]what are y0u uploading&#xff1f; 右击查看源码…

查询品牌涉及两张表(brand、brand_admin_mapping)

文章目录 1、BrandController2、AdminCommonService3、BrandApiService3、BrandCommonService4、BrandSqlService涉及的表SQL 查询逻辑参数处理执行查询完整 SQL 逻辑参数映射总结 SELECT * FROM brand_admin_mapping WHERE admin_id 252SELECT * FROM brand WHERE id 44SELE…

k8s 为什么需要Pod?

Pod&#xff0c;是 Kubernetes 项目中最小的 API 对象&#xff0c;更加专业的说&#xff0c;Pod&#xff0c;是 Kubernetes 项目的原子调度单位。 Pod 是 Kubernetes 里的原子调度单位。这就意味着&#xff0c;Kubernetes 项目的调度器&#xff0c;是统一按照 Pod 而非容器的资…

如何在Ubuntu中利用repo和git地址下载获取imx6ull的BSP

01-设置git的用户名和邮箱 git config --global user.name "suwenhao" git config --global user.email "2487872782qq.com"这里不设置的话后面在第5步的repo配置中还是会要求输入&#xff0c;而且以后进行相关操作都要输入&#xff0c;不妨现在就进行配置…

【机器学习】基于SVM、逻辑回归和CNN的手写数字识别:性能对比与应用分析

基于SVM、逻辑回归和CNN的手写数字识别&#xff1a;性能对比与应用分析 1 基于SVM对手写数字识别2 基于逻辑回归对手写数字进行识别3 基于CNN对手写数字进行识别总结对比分析 1 基于SVM对手写数字识别 在使用SVM方法对手写数字进行识别的时候&#xff0c;我采用了一对多&#…

Elasticsearch ILM 故障排除:常见问题及修复

作者&#xff1a;来自 Elastic Stef Nestor 大家好&#xff01;我们的 Elasticsearch 团队正在不断改进我们的索引生命周期管理 (index Lifecycle Management - ILM) 功能。当我第一次加入 Elastic Support 时&#xff0c;我通过我们的使用 ILM 实现自动滚动教程快速上手。在帮…

【html网页页面009】html+css制作学校官网主题网页制作含登录(5页面附效果及源码)

校园网站主题网页制作 &#x1f964;1、写在前面&#x1f367;2、涉及知识&#x1f333;3、网页效果&#x1f308;4、网页源码4.1 html4.2 CSS4.3 源码获取w034学校网页源码及介绍链接 &#x1f40b;5、作者寄语 &#x1f964;1、写在前面 学校网站主题的网页 一共5个页面 网…

JavaScript柯里化和组合函数以及严格模式介绍

柯里化介绍 柯里化的结构 简化版本 让函数的职责单一 柯里化的复用 对某些逻辑进行复用 打印日志的柯里化 自动化柯里化函数 实现柯理化函数 1.柯里化函数是对函数进行处理的方法&#xff0c;所以参数就为一个函数&#xff0c;这里取名w为fn 2.定义一个函数curried&#xff0…

查看 tomcat信息 jconsole.exe

Where is the jconsole.exe? location: JDK/bin/jconsole.exe

【SpringBoot】Day11-09 参数配置化

为什么需要参数配置化 对于这些配置信息是直接硬编码&#xff0c;写死在java程序中的&#xff0c;存在几个问题&#xff1a; 如果这些参数发生变化了&#xff0c;就必须在源程序代码中改动这些参数&#xff0c;然后需要重新进行代码的编译&#xff0c;将Java代码编译成class字节…

企业迎接现场网络安全检查准备

企业安全负责人一听到主管单位单位要来现场进行网络安全就紧张可是对于不少重点企业来说&#xff0c;现场检查又是不可避免的&#xff0c;今天就谈谈企业如何准备网络安全检查。 网络安全现场检查类型&#xff1a; 常规检查&#xff1a;年度例行重要信息系统网络安全检查&…

UE5.5 Geometry库平面切割原理分析

平面切割--FMeshPlaneCut 平面定义: 面上一个点 法线 算法流程如下 求几何体所有顶点和面的有向距离(Signs) Sign计算&#xff1a; float Sign (VertexPos - PlaneOrigin).Dot(PlaneNormal); 遍历所有几何体所有交叉边, 进行SplitEdge 对于位于切割面两侧的交叉边(Sign…

VideoConvertor.java ffmpeg.exe

VideoConvertor.java ffmpeg.exe 视频剪切原理 入点 和 出点 选中时间点&#xff0c;导出

react hooks讲解--通俗易懂版

面试必备&#xff01; useState:状态管理 useState有两个状态&#xff0c;一个是status&#xff0c;一个是setStatus setStatus修改数据后&#xff0c;会触发<App/>的re-render 什么是re-render? re-render:重新渲染&#xff0c;re-render并不意味着dom会更新&#x…

MongoDB集群的介绍与搭建

MongoDB集群的介绍与搭建 一.MongoDB集群的介绍 注意&#xff1a;Mongodb是一个比较流行的NoSQL数据库&#xff0c;它的存储方式是文档式存储&#xff0c;并不是Key-Value形式&#xff1b; 1.1集群的优势和特性 MongoDB集群的优势主要体现在以下几个方面&#xff1a; (1)高…

基于 Python、OpenCV 和 PyQt5 的人脸识别上课打卡系统

大家好&#xff0c;我是Java徐师兄&#xff0c;今天为大家带来的是基于 Python、OpenCV 和 PyQt5 的人脸识别上课签到系统。该系统采用 Python 语言开发&#xff0c;开发过程中采用了OpenCV框架&#xff0c;Sqlite db 作为数据库&#xff0c;系统功能完善 &#xff0c;实用性强…

element Plus中 el-table表头宽度自适应,不换行

在工作中&#xff0c;使用el-table表格进行开发后&#xff0c;遇到了小屏幕显示器上显示表头文字会出现换行展示&#xff0c;比较影响美观&#xff0c;因此需要让表头的宽度变为不换行&#xff0c;且由内容自动撑开。 以下是作为工作记录&#xff0c;用于demo演示教程 先贴个…

GitLab基础环境部署:Ubuntu 22.04.5系统在线安装GitLab 17.5.2实操手册

文章目录 GitLab基础环境部署&#xff1a;Ubuntu 22.04.5系统在线安装GitLab 17.5.2实操手册一、环境准备1.1 机器规划1.2 环境配置1.2.1 设置主机名1.2.2 停止和禁用防火墙1.2.3 更新系统 二、GitLab安装配置2.1 安装GitLab所需的依赖包2.2 添加GitLab存储库2.2.1 将GitLab存储…

1.3.3 存储系统

目录 存储器分类存储器的层次结构主存储器高速缓存的特点及组成外存储器的种类和特点 存储器分类 存储器按照所处位置、制作材料、访问方式、寻址方式、工作方式可以分成多种类型。 位置&#xff1a;在主机或主板上的是内存&#xff0c;否则是外存。材料&#xff1a;磁存储器&…

【PyQt5教程 一】Qt Designer 安装及其使用方法说明,附程序源码

目录 一、PyQt5介绍&#xff1a; &#xff08;1&#xff09;PyQt简介&#xff1a; &#xff08;2&#xff09;PyQt API&#xff1a; &#xff08;3&#xff09;支持的环境&#xff1a; &#xff08;4&#xff09;安装&#xff1a; &#xff08;5&#xff09;配置环境变量…