QSqlTableModel的使用
实例功能
这边使用一个实例显示数据库 demodb 中 employee 数据表的内容,实现编辑、插入、删除的操作,实现数据的排序和记录过滤,还实现 BLOB 类型字段 Photo 中存储照片的显示、导入等操作,运行界面如下图:
在上图中,左侧数据表格是一个 QTableView 组件,设置一个 QSqlTableModel 类的变量作为数据模型后就可以显示数据表的内容。右侧的一些编辑框、下拉列表框等。界面组件通过 QDataWidgetMapper 类的实例设置为某个字段关联,自动显示字段内容。但是没有现成的组件可以通过字段映射显示图片。为此需要使用一个 QLabel 来显示图片。所以图片的导入和显示等操作需要额外实现。
QTableView 显示内容有缺省的代理组件,一般是自动使用 QLineEdit 组件。但是对于某些字段期望通过下拉列表框来输入,例如“性别”和“部门”。为此,还设计了自定义数据代理类。
工具栏上的按钮根据当前状态自动可用或禁用,特别是“保存”和“取消”两个按钮在数据有改动后可以使用,使用过之后又不可使用。
主窗口设计
Action 工具栏如下图所示,其他在上面已经说明:
以下是主窗口 MainWindow 的定义:
class MainWindow : public QMainWindow
{Q_OBJECTprivate:QSqlDatabase DB;//数据库连接QSqlTableModel *tabModel; //数据模型QItemSelectionModel *theSelection; //选择模型QDataWidgetMapper *dataMapper; //数据映射QWComboBoxDelegate delegateSex; //自定义数据代理,性别QWComboBoxDelegate delegateDepart; //自定义数据代理,部门void openTable();//打开数据表void getFieldNames();//获取字段名称,填充“排序字段”的comboBox
public:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);// QTableView的SelectionModel的行发生了变化,进行处理void on_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);///void on_actOpenDB_triggered();void on_actRecAppend_triggered();void on_actRecInsert_triggered();void on_actRevert_triggered();void on_actSubmit_triggered();void on_actRecDelete_triggered();void on_actPhoto_triggered();void on_actPhotoClear_triggered();void on_radioBtnAscend_clicked();void on_radioBtnDescend_clicked();void on_radioBtnMan_clicked();void on_radioBtnWoman_clicked();void on_radioBtnBoth_clicked();void on_comboFields_currentIndexChanged(int index);void on_actScan_triggered();private:Ui::MainWindow *ui;
};
MainWindow 类中定义了几个私有变量:
- QSqlDatabase DB,用于加载数据库驱动和建立与数据库之间的连接。
- QSQLTab 了 Model* tabModel,用于指定某个数据表,作为数据表的数据模型。
- QItemSelectionModel* theSelection,作为 tabModel 的选择模型,提供 currentChange()、currentRowChanged()等信号,在 tabModel 选择的字段发生变化、当前记录发生变化时发射信号,以便应用程序控制响应。例如在 currentChanged()信号发射时,检查 tabModel 是否有数据被修改,从而更新“保存”和“取消”按钮的状态。
- QDataWidgetMapper* dataMapper 用于实现界面组件和 tabModel 的字段之间的映射。
- QWComboBoxDelegate 是一个自定义的基于 QComboBox 的代理类,delegateSex 和 delegateDepart 用作 tableView 中的“性别”和“部门”字段的代理组件。
- on_currentChanged() 用于检查数据表内容是否有修改,从而更新按钮状态。
- on_currentRowChanged() 用于在当前记录发生变化的时候,从新记录中提取图片并更新到界面。
MainWindow 的构造函数如下,主要是对 tableView 的一些显示属性设置:
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);this->setCentralWidget(ui->splitter);// tableView显示属性设置ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);ui->tableView->setAlternatingRowColors(true);
// ui->tableView->resizeColumnsToContents();
// ui->tableView->horizontalHeader()->setStretchLastSection(true);
}
打开数据表
点击“打开”按钮时将加载 SQLite 数据库驱动、打开数据库文件、连接 employee 数据表并设置显示属性,并创建 tableView 显示的代理组件,设置数据源与界面组件的映射等,代码如下:
void MainWindow::on_actOpenDB_triggered()
{//打开数据表QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","","SQL Lite数据库(*.db *.db3)");if (aFile.isEmpty()) //选择SQL Lite数据库文件return;//打开数据库DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动DB.setDatabaseName(aFile); //设置数据库名称if (!DB.open()) //打开数据库{QMessageBox::warning(this, "错误", "打开数据库失败",QMessageBox::Ok,QMessageBox::NoButton);return;}//打开数据表openTable();
}
这里需要使用 QSqlDatabase 的几个函数设置数据库登录参数,setDatabaseName()设置数据库名称,对于 SQLite 数据库,就设置为数据库文件。如果是网络型数据库,如 Oracle、MS SQL Server 等,还需要使用 setHostName() 设置数据库主机名,setUserName() 设置数据库用户名,setPassword() 设置数据登录密码。对于 SQLite 数据库只要设置数据库文件即可。
数据库连接与登录参数设置后,调用 QSqlDatabase::open()
函数打开数据库。如果成功打开再调用 openTable() 打开数据表进行相关操作。openTable() 函数代码如下:
void MainWindow::openTable()
{//打开数据表tabModel=new QSqlTableModel(this,DB);//数据表tabModel->setTable("employee"); //设置数据表tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);//数据保存方式,OnManualSubmit , OnRowChangetabModel->setSort(tabModel->fieldIndex("empNo"),Qt::AscendingOrder); //排序if (!(tabModel->select()))//查询数据{QMessageBox::critical(this, "错误信息","打开数据表错误,错误信息\n"+tabModel->lastError().text(),QMessageBox::Ok,QMessageBox::NoButton);return;}//字段显示名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("Height"),Qt::Horizontal,"身高");tabModel->setHeaderData(tabModel->fieldIndex("Birthday"),Qt::Horizontal,"出生日期");tabModel->setHeaderData(tabModel->fieldIndex("Mobile"),Qt::Horizontal,"手机");tabModel->setHeaderData(tabModel->fieldIndex("Province"),Qt::Horizontal,"省份");tabModel->setHeaderData(tabModel->fieldIndex("City"),Qt::Horizontal,"城市");tabModel->setHeaderData(tabModel->fieldIndex("Department"),Qt::Horizontal,"部门");tabModel->setHeaderData(tabModel->fieldIndex("Education"),Qt::Horizontal,"学历");tabModel->setHeaderData(tabModel->fieldIndex("Salary"),Qt::Horizontal,"工资");tabModel->setHeaderData(tabModel->fieldIndex("Memo"),Qt::Horizontal,"备注"); //这两个字段不再tableView中显示tabModel->setHeaderData(tabModel->fieldIndex("Photo"),Qt::Horizontal,"照片");theSelection=new QItemSelectionModel(tabModel);//关联选择模型
//theSelection当前项变化时触发currentChanged信号connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
//选择行变化时connect(theSelection,SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentRowChanged(QModelIndex,QModelIndex)));ui->tableView->setModel(tabModel);//设置数据模型ui->tableView->setSelectionModel(theSelection); //设置选择模型ui->tableView->setColumnHidden(tabModel->fieldIndex("Memo"),true);//隐藏列ui->tableView->setColumnHidden(tabModel->fieldIndex("Photo"),true);//隐藏列//tableView上为“性别”和“部门”两个字段设置自定义代理组件QStringList strList;strList<<"男"<<"女";bool isEditable=false;delegateSex.setItems(strList,isEditable);ui->tableView->setItemDelegateForColumn(tabModel->fieldIndex("Gender"),&delegateSex); //Combbox选择型strList.clear();strList<<"销售部"<<"技术部"<<"生产部"<<"行政部";isEditable=true;delegateDepart.setItems(strList,isEditable);ui->tableView->setItemDelegateForColumn(tabModel->fieldIndex("Department"),&delegateDepart); //Combbox选择型//创建界面组件与数据模型的字段之间的数据映射dataMapper= new QDataWidgetMapper();dataMapper->setModel(tabModel);//设置数据模型dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);//// dataMapper->setItemDelegate(new QSqlRelationalDelegate(this)); //含有外键的
//界面组件与tabModel的具体字段之间的联系dataMapper->addMapping(ui->dbSpinEmpNo,tabModel->fieldIndex("empNo"));dataMapper->addMapping(ui->dbEditName,tabModel->fieldIndex("Name"));dataMapper->addMapping(ui->dbComboSex,tabModel->fieldIndex("Gender"));dataMapper->addMapping(ui->dbSpinHeight,tabModel->fieldIndex("Height"));dataMapper->addMapping(ui->dbEditBirth,tabModel->fieldIndex("Birthday"));dataMapper->addMapping(ui->dbEditMobile,tabModel->fieldIndex("Mobile"));dataMapper->addMapping(ui->dbComboProvince,tabModel->fieldIndex("Province"));dataMapper->addMapping(ui->dbEditCity,tabModel->fieldIndex("City"));dataMapper->addMapping(ui->dbComboDep,tabModel->fieldIndex("Department"));dataMapper->addMapping(ui->dbComboEdu,tabModel->fieldIndex("Education"));dataMapper->addMapping(ui->dbSpinSalary,tabModel->fieldIndex("Salary"));dataMapper->addMapping(ui->dbEditMemo,tabModel->fieldIndex("Memo"));// dataMapper->addMapping(ui->dbPhoto,tabModel->fieldIndex("Photo")); //图片无法直接映射dataMapper->toFirst();//移动到首记录getFieldNames();//获取字段名称列表,填充ui->groupBoxSort组件//更新actions和界面组件的使能状态ui->actOpenDB->setEnabled(false);ui->actRecAppend->setEnabled(true);ui->actRecInsert->setEnabled(true);ui->actRecDelete->setEnabled(true);ui->actScan->setEnabled(true);ui->groupBoxSort->setEnabled(true);ui->groupBoxFilter->setEnabled(true);
}
数据模型的创建和属性设置
首先创建 QSqlTableModel 类型的私有变量 tabModel,并且在创建时制定了数据库连接,然后用 setTable() 来指定数据表;setSort() 函数设置排序字段和排序方式,函数原型如下:
void QSqlTableModel::setSort(int column, Qt::SortOrder order);
第一参数是排序的列号,第二个参数是枚举类型,表示排序方式。Qt::AscendingOrder
表示升序,Qt::DescendingOrder
表示降序。
QSqlTableModel::setEditStrategy()函数用于设置编辑策略,参数是枚举类型 QSqlTableModel::EditStrategy
,取值如下:
- QSqlTableModel::OnFieldChange,字段变化时马上更新数据库。
- QSqlTableModel::OnRowChange,当前行变化时自动更新数据库。
- QSqlTableModel::OnManualSubmit,所有修改暂时缓存,手动调用 submitAll() 保存修改,或调用 revertAll() 函数取消所有未保存的修改。
表头设置
QSqlTableModel::setHeaderData() 函数用于设置每个字段的表头数据,主要是设置显示标题。如果不进行表头设置,在 TableView 里显示时将显示字段名作为表头。例如,设置“Name”字段的显示标题为“姓名”的代码如下:
tabModel->setHeaderData(tabModel->fieldIndex("Name"), Qt::Horizontal, "姓名");
这里需要注意第一个参数是字段的序号,使用 fieldIndex()
函数可以自动识别序号。
选择模型和信号的作用
为数据模型创建一个选择模型的代码如下:
theSelection = new QitemSelectionModel(tabModel);
选择模型的作用是当用户在 TableView 组件上操作时,获取当前选择的行、列信息,并且在选择的单元格变化时发射 currentChanged() 信号,在当前行变化时发射 currentRowChanged() 信号。为 currentChanged() 信号编写槽函数 on_currentChanged()
,获取 tabModel->isDirty()
函数的值,根据是否有未提交的修改,更新工具栏按钮状态。槽函数 on_currentChanged()
代码如下:
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{//更新actPost和actCancel 的状态Q_UNUSED(current);Q_UNUSED(previous);ui->actSubmit->setEnabled(tabModel->isDirty()); //有未保存修改时可用ui->actRevert->setEnabled(tabModel->isDirty());
}
为 currentRowChanged() 信号编写槽函数 on_currentRowChanged()
,用于在当前行变化时,从新的记录里提取 Photo 字段的内容,并将图片在 QLabel 组件中显示出来。on_currentRowChanged()
的代码如下:
void MainWindow::on_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
{Q_UNUSED(previous);
// 行切换时的状态控制ui->actRecDelete->setEnabled(current.isValid());ui->actPhoto->setEnabled(current.isValid());ui->actPhotoClear->setEnabled(current.isValid());if (!current.isValid()){ui->dbLabPhoto->clear(); //清除图片显示return;}dataMapper->setCurrentIndex(current.row()); //更细数据映射的行号int curRecNo=current.row();//获取行号QSqlRecord curRec=tabModel->record(curRecNo); //获取当前记录if (curRec.isNull("Photo")) //图片字段内容为空ui->dbLabPhoto->clear();else{QByteArray data=curRec.value("Photo").toByteArray();QPixmap pic;pic.loadFromData(data);ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));}
}
添加、插入与删除记录
工具栏上有“添加”,“插入”和“删除”三个按钮用于记录操作。添加按钮的槽函数如下:
void MainWindow::on_actRecAppend_triggered()
{//添加记录tabModel->insertRow(tabModel->rowCount(),QModelIndex()); //在末尾添加一个记录QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1);//创建最后一行的ModelIndextheSelection->clearSelection();//清空选择项theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//设置刚插入的行为当前选择行int currow=curIndex.row(); //获得当前行tabModel->setData(tabModel->index(currow,0),2000+tabModel->rowCount()); //自动生成编号tabModel->setData(tabModel->index(currow,2),"男");
// 插入行时设置缺省值,需要在primeInsert()信号里去处理
}
QSqlTableModel::insertRow(int row)函数在数据模型的 row 行前插入一行记录,如果 row 大于等于总函数,就在最后一行添加。使用代码如下:
void MainWindow::on_actRecInsert_triggered()
{//插入记录QModelIndex curIndex=ui->tableView->currentIndex();tabModel->insertRow(curIndex.row(),QModelIndex());theSelection->clearSelection();//清除已有选择theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}
删除数据的代码如下:
void MainWindow::on_actRecDelete_triggered()
{//删除当前记录QModelIndex curIndex=theSelection->currentIndex();//获取当前选择单元格的模型索引tabModel->removeRow(curIndex.row()); //删除最后一行
}
在插入或删除记录操作没有提交之前,TableView 的左侧表头会记录编辑状态;在保存记录之后,标记会消失,删除的记录也会从 TableView 里删除。
保存和取消修改
当前 demo 在打开数据表的时候,将编辑策略设置为 OnManualSubmit
,即手动提交修改。当前数据模型的数据被修改后,不管是直接修改字段值,还是插入或删除记录,在未提交修改前,QSqlTableModel::isDirty()
函数返回 true
,利用这个函数在自定义槽函数 on_currentChanged()
里修改 actSubmit 和 actRevert 两个 Action 的使能状态。“保存”和“取消修改”的槽函数代码如下:
void MainWindow::on_actRevert_triggered()
{//取消修改tabModel->revertAll();ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);
}void MainWindow::on_actSubmit_triggered()
{//保存修改bool res=tabModel->submitAll();if (!res)QMessageBox::information(this, "消息", "数据保存错误,错误信息\n"+tabModel->lastError().text(),QMessageBox::Ok,QMessageBox::NoButton);else{ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);}
}
数据遍历
工具栏上的“涨工资”按钮用于将数据表内所有记录的 salary 字段内容增加 10%,演示了记录遍历的功能,代码如下:
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, "消息", "涨工资计算完毕",QMessageBox::Ok,QMessageBox::NoButton);
}
记录排序
QSqlTableModel 的 setSort()
函数设置数据表根据某个字段按照升序或降序排列,实际上就是设置了 SQL 的 ORDER BY
语句。这里在打开数据表的时,调用了 getFieldNames()
函数将数据表的所有字段名添加到界面上的“下拉框”。“排序字段”、“下拉框列表”、“升序”和“降序”的操作如下:
void MainWindow::on_comboFields_currentIndexChanged(int index)
{//选择字段进行排序if (ui->radioBtnAscend->isChecked())tabModel->setSort(index,Qt::AscendingOrder);elsetabModel->setSort(index,Qt::DescendingOrder);tabModel->select();
}
void MainWindow::on_radioBtnAscend_clicked()
{//升序tabModel->setSort(ui->comboFields->currentIndex(),Qt::AscendingOrder);tabModel->select();
}void MainWindow::on_radioBtnDescend_clicked()
{//降序tabModel->setSort(ui->comboFields->currentIndex(),Qt::DescendingOrder);tabModel->select();
}
记录过滤
QSqlTableModel 的 setFilter()
函数设置记录过滤条件,实际上就是 SQL 语句中的 WHERE。界面上的“数据过滤”分组框里有三个 RadioButton;分别为“男”、“女”和“全部显示”,对应的参函数如下:
void MainWindow::on_radioBtnMan_clicked()
{tabModel->setFilter(" Gender='男' ");
// tabModel->select();
}void MainWindow::on_radioBtnWoman_clicked()
{tabModel->setFilter(" Gender='女' ");
// tabModel->select();
}void MainWindow::on_radioBtnBoth_clicked()
{tabModel->setFilter("");
}
调用 setFilter()
后无需 select 就可以立刻刷新记录,如果需要取消过滤条件,只要设置为空字符串即可。
参考资料:https://github.com/0voice
相关文章:
QSqlTableModel的使用
实例功能 这边使用一个实例显示数据库 demodb 中 employee 数据表的内容,实现编辑、插入、删除的操作,实现数据的排序和记录过滤,还实现 BLOB 类型字段 Photo 中存储照片的显示、导入等操作,运行界面如下图: 在上图中…...
构建高可用系统设计OpenStack、Docker、Mesos和Kubernetes(简称K8s)
如果构建高可用、高并发、高效运维的大型系统 大型系统架构设计包括业务层设计、服务层设计、基础架层设计、存储层设计、网络层协同设计来完成。 一、业务层 根据主要业务范畴的分类和特征提取,抽象出独立的业务系统,分别统计系统的用户角色群体、访…...
CondaValueError: Malformed version string ‘~‘: invalid character(s).
问题描述:在window下使用conda安装任何包都会报错。报错信息是CondaValueError: Malformed version string ~: invalid character(s). 解决办法:把.condarc文件的源地址删除(八成是源地址访问不了了),只保存默认的&am…...
uniapp图片上传预览uni.chooseImage、uni.previewImage
文章目录 1.上传图片2.预览图片 1.上传图片 uni.chooseImage(OBJECT) 从本地相册选择图片或使用相机拍照。 App端如需要更丰富的相机拍照API(如直接调用前置摄像头),参考plus.camera 微信小程序从基础库 2.21.0 开始, wx.choos…...
代码随想录算法训练营第三十二天 | 509. 斐波那契数 | 70. 爬楼梯 | 746. 使用最小花费爬楼梯
Day 32 总结 自己实现中遇到哪些困难今日收获,记录一下自己的学习时间 12:30 - 21:30 理论基础 代码随想录 动态规划 问题有很多的重叠子问题需要解决,状态涉及推导 DP 5部曲 DP数组含义 状态转移公式 dp数组初始化 数组遍历顺序 举例推导 视频&a…...
Flink常见面试题
1、Flink 的四大特征(基石) 2、Flink 中都有哪些 Source,哪些 Sink,哪些算子(方法) 预定义Source 基于本地集合的source(Collection-based-source) 基于文件的source(…...
SpringCloud之Config:从基础到高级应用
目录 一、SpringCloud Config 简介1、SpringCloud Config 概述(1)核心概念(2)SpringCloud Config 的特点(3)应用场景(4)工作原理(5)优势(6&#x…...
redis 底层数据结构
概述 Redis 6 和 Redis 7 之间对比: Redis6 和 Redis7 最大的区别就在于 Redis7 已经用 listpack 替代了 ziplist. 以下是基于 Redis 7基础分析。 RedisObject Redis是⼀个<k,v>型的数据库,其中key通常都是string类型的字符串对象,⽽…...
机器学习之RLHF(人类反馈强化学习)
RLHF(Reinforcement Learning with Human Feedback,基于人类反馈的强化学习) 是一种结合人类反馈和强化学习(RL)技术的算法,旨在通过人类的评价和偏好优化智能体的行为,使其更符合人类期望。这种方法近年来在大规模语言模型(如 OpenAI 的 GPT 系列)训练中取得了显著成…...
openwrt利用nftables在校园网环境下开启nat6 (ipv6 nat)
年初写过一篇openwrt在校园网环境下开启ipv6 nat的文章,利用ip6tables控制ipv6的流量。然而从OpenWrt22版本开始,系统内置的防火墙变为nftables,因此配置方法有所改变。本文主要参考了OpenWRT使用nftables实现IPv6 NAT 这篇文章。 友情提示 …...
Vue3+node.js实现注册
文章目录 前端代码实现后端代码实现 效果图 前端代码实现 <template><div class"register-container"><el-card class"register-card"><template #header><div class"card-header"><span>注册</span&…...
LabVIEW将TXT文本转换为CSV格式(多行多列)
在LabVIEW中,将TXT格式的文本文件内容转换为Excel格式(即CSV文件)是一项常见的数据处理任务,适用于将以制表符、空格或其他分隔符分隔的数据格式化为可用于电子表格分析的形式。以下是将TXT文件转换为Excel(CSV&#x…...
SpringBoot源码-Spring Boot启动时控制台为何会打印logo以及自定义banner.txt文件控制台打印
1.当我们启动一个SpringBoot项目的时候,入口程序就是main方法,而在main方法中就执行了一个run方法。 SpringBootApplication public class StartApp {public static void main(String[] args) {// testSpringApplication.run(StartApp.class);} }publi…...
【笔记】软技能
硬技能:操控世界的能力,处理对象为【物】。软技能:影响他人的能力,处理对象为【人】。软技能包括一个人的情商、个性、社交礼仪、沟通、语言、个人习惯,还有解决问题的能力、领导能力、时间管理能力等一切非技术能力。…...
试题转excel;试题整理工具;试卷转excel;word转excel
一、问题描述 我父亲是一名教师,偶尔会需要将试卷转excel,方便管理处理一些特别重要的题目 于是,就抽空写一个专门将试题转excel的工具,便于各位教师从业者和教育行业的朋友更好的整理试题,减少一点重复枯燥的工作 …...
【热门主题】000072 分布式数据库:开启数据管理新纪元
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...
常见靶场的搭建
漏洞靶场 渗透测试(漏洞挖掘)切忌纸上谈兵,学习渗透测试(漏洞挖掘)知识的过程中,我们通常需要一个包含漏洞的测试环境来进行训练。而在非授权情况下,对于网站进行渗透测试攻击,是触及…...
C语言——链表
1 链表基础 1 什么是链表 !!!链表相当于多个结构体变量链接在一起!!! //链表节点结构 struct Node //数据域和指针域 {int data; //数据域//struct Student data;数据尽量不写在链表结构体里面…...
【经典】星空主题的注册界面HTML,CSS,JS
目录 界面展示 完整代码 说明: 这是一个简单的星空主题的注册界面,使用了 HTML 和 CSS 来实现一个背景为星空效果的注册页面。 界面展示 完整代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8&…...
94.【C语言】解析预处理(2)
目录 1.带有副作用的宏参数 代码 一个判断最大值的宏代码 运行结果 分析 "副作用"的解释 2.宏替换规则 解释 3.宏和函数的对比 附一张对比表 承接93.【C语言】解析预处理(1)文章 1.带有副作用的宏参数 代码 一个判断最大值的宏代码 #define MAX(a, b) (…...
(数据结构与算法)如何提高学习算法的效率?面试算法重点有哪些?面试需要哪些能力?
面试官眼中的求职者 通过对你算法的考察!!!! 缩进太多!!一般不要超过三层!!!缩进越少,bug越少;逻辑比较复杂,把这些包装成为函数&…...
STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58
STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58 STM32F407芯片的OPTION Byte全面解析 STM32F407芯片是STMicroelectronics推出的一款功能强大的微控制器,广泛应用于工业控制、通信和消费电子等领域。其中,OPTION Byte࿰…...
MySQL主从复制
华子目录 实验环境准备修改配置文件 实验主开启bin-log日志创建用于主从复制的用户master配置salve配置 测试 添加一台新的slave,如何实现数据的全部同步呢什么环境下主比较多,什么环境下从比较多?延迟复制测试 并行复制gtid模式未启用gtid时…...
贝叶斯统计:高斯分布均值μ的后验分布推导
使用贝叶斯统计方法 均值 ( μ \mu μ ) 的后验分布解析 在贝叶斯统计中,后验分布表示在观察到数据后,对参数的更新后的信念。本篇文章将结合高斯分布的假设,详细解析均值 ( μ \mu μ ) 的后验分布推导过程,并对 ( μ \mu μ…...
linux常用指令都是工作中遇到的
前端打war包 jar -cvf dist.war *创建 WAR 文件的命令 jar -cvf dist.war * 用于将当前目录下的所有文件和文件夹打包成一个名为 dist.war 的 WAR 文件。以下是该命令的详细解释: jar: Java Archive 工具,用于创建 JAR、WAR 或 EAR 文件。 -c: 创建新的…...
亚马逊自研大语言模型 Olympus 即将亮相,或将在 LLM 竞赛中掀起新波澜
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
droppath
DropPath 是一种用于正则化深度学习模型的技术,它在训练过程中随机丢弃路径(或者说随机让某些部分的输出变为零),从而增强模型的鲁棒性和泛化能力。 代码解释: import torch import torch.nn as nn # 定义 DropPath…...
通信与网络安全之IPSEC
IPSec(IP Security)是IETF制定的为保证在Internet上传送数据的安全保密性能的三层隧道加密协议。IPSec在网络层对IP报文提供安全服务。IPSec协议本身定义了如何在IP数据包中增加字段来保证IP包的完整性、 私有性和真实性,以及如何加密数据包。…...
Linux内核编译流程(Ubuntu24.04+Linux Kernel 6.8.12)
万恶的拯救者,使用Ubuntu没有声音,必须要自己修改一下Linux内核中的相关驱动逻辑才可以,所以被迫学习怎么修改内核&编译内核,记录如下 准备工作 下载Linux源码:在Linux发布页下载并使用gpg签名验证 即:…...
什么是GAN?
一、基本概念 生成对抗网络(Generative Adversarial Network,GAN)是一种由两个神经网络共同组成深度学习模型:生成器(Generator)和判别器(Discriminator)。这两个网络通过对抗的方式…...
torch_geometric使用手册-Creating Graph Datasets(专题四)
虽然 PyG 已经提供了很多有用的数据集,但你可能希望创建自己的数据集,使用自己收集的数据或非公开的数据。 自己实现数据集是非常简单的,你可能想查看源代码,了解各种数据集是如何实现的。然而,这里简要介绍一下如何设置你自己的数据集。 我们提供了两个抽象类用于数据集…...
编程语言之Python
Python是一种高级编程语言,自其诞生以来,便因其简洁明了的语法、强大的功能和广泛的应用领域而备受青睐。以下是对Python的详细介绍,包括其历史、特点、应用领域,以及通过代码示例展示其语法、库、函数等关键概念。同时࿰…...
【Go】-调度器简介
目录 数据结构 G M P 调度器启动 创建 Goroutine 初始化结构体 运行队列 调度信息 调度循环 小结 数据结构 Go的运行时调度器的三个重要组成部分 — 线程 M、Goroutine G 和处理器 P: 图 6-29 Go 语言调度器 G — 表示 Goroutine,它是一个待…...
在Ubuntu 22.04上设置Python 3的Jupyter Notebook
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 Jupyter Notebook 是一个作为 Web 应用程序的交互式计算命令 shell。该工具可与多种语言一起使用,包括 Python、Julia…...
通讯专题4.1——CAN通信之计算机网络与现场总线
从通讯专题4开始,来学习CAN总线的内容。 为了更好的学习CAN,先从计算机网络与现场总线开始了解。 1 计算机网络体系的结构 在我们生活当中,有许多的网络,如交通网(铁路、公路等)、通信网(电信、…...
将jar包导入maven
1.将jar包放repository 2.执行命令:mvn install:install-file -DgroupIdcom.oracle -DartifactIdojdbc7 -Dversion12.1.0.2 -Dpackagingjar -DfileD:\dev\utils\idea\repository\ojdbc7.jar -Dfile: 指定要安装的JAR文件的路径。 -DgroupId: 指定项目的groupId。 -…...
Mysql实现定时自动备份(Windows环境)
一.新建数据库备份目录 二.新建批处理文件 创建批处理文件mysql_backup.bat echo off set BACKUP_DIRD:\backup set MYSQL_USERroot set MYSQL_PASS123456 set MYSQL_HOSTlocalhost set DATABASE_NAMEphoenix set DATE%date:~0,4%-%date:~5,2%-%date:~8,2%_%time:~0,2%-%time…...
kafka数据在服务端时怎么写入的
学习背景 接着上篇,我们来聊聊kafka数据在服务端怎么写入的 服务端写入 在介绍服务端的写流程之前,我们先要理解服务端的几个角色之间的关系。 假设我们有一个由3个broker组成的kafka集群,我们在这个集群上创建一个topic叫做shitu-topic&…...
2024算法基础公选课练习七(BFS1)
一、前言 还是偏基础的bfs,但是有几个题不是很好写 二、题目总览 三、具体题目 3.1 问题 A: 数据结构-队列-奇怪的电梯 我的代码 可以看成求一维平面的bfs最短路 #include <bits/stdc.h> using i64 long long; using pii std::pair<int,int>; co…...
算法刷题Day1
BM47 寻找第k大 第一天就随便记录吧,万事开头难,我好不容易开的头,就别难为自己,去追求高质量了。嘿嘿嘿 题目 传送门 解题思路一:维护一个大小为k的最小堆。最后返回堆顶元素。 代码: # # 代码中的类名…...
你还没有将 Siri 接入GPT对话功能吗?
由于各种原因,国内ios用户目前无缘自带 AI 功能,但是这并不代表国内 ios 无法接入 AI 功能,接下来手把手带你为iPhone siri 接入 gpt 对话功能。 siri 接入 chatGPT 暂时还无法下载 ChatGPT app,或者没有账号的读者可以直接跳到…...
LabVIEW 标准状态机设计模式
LabVIEW 标准状态机设计模式 LabVIEW 软件框架介绍LabVIEW编程模式及其应用分析状态机模式的类型分析标准状态机设计模式及状态机应用学习顺序结构它的一个缺点是什么? 状态机结构 LabVIEW 软件框架介绍 源于虚拟仪器技术的LabVIEW程序设计语言,从被创建…...
Scala学习记录,统计成绩
统计成绩练习 1.计算每个同学的总分和平均分 2.统计每个科目的平均分 3.列出总分前三名和单科前三名,并保存结果到文件中 解题思路如下: 1.读入txt文件,按行读入 2.处理数据 (1)计算每个同学的总分平均分 import s…...
使用 client-go 实现 Kubernetes 节点 Drain:详解与实战教程
在 Kubernetes 中使用 client-go 实现 drain 功能涉及多个步骤,需要模仿 kubectl drain 的行为。这包括将节点标记为不可调度(cordon)、驱逐 Pod,并处理 DaemonSet 和不可驱逐 Pod 的逻辑。以下是实现 drain 的主要步骤࿱…...
C#VB.Net项目一键多国语言显示
如何在项目什么都不做一键支持多国语言显示 开始我们的一键快捷使用之旅 01.创建多语言项目 02.一键批量窗口开启本地化,添加选中内容添加Mu方法 03.一键快捷翻译 04.运行查看效果 01.创建多语言项目 创建多语言项目前,请先下载安装,注册并登录. 为了便于演示这…...
【关闭or开启电脑自带的数字键盘】
目录 一、按数字键盘左上角的按键【NumLK Scroll】 二、修改注册表中数字键盘对应的数值【InitialKeyboardIndicators】 1、步骤: 2、知识点: 一、按数字键盘左上角的按键【NumLK Scroll】 这是最简单快捷的方法。 关闭后若想开启,再按一…...
如何在Bash中等待多个子进程完成,并且当其中任何一个子进程以非零退出状态结束时,使主进程也返回一个非零的退出码?
文章目录 问题回答参考 问题 如何在 Bash 脚本中等待该脚本启动的多个子进程完成,并且当这其中任意一个子进程以非零退出码结束时,让该脚本也返回一个非零的退出码? 简单的脚本: #!/bin/bash for i in seq 0 9; docalculations $i & d…...
Asio2网络库
header only,不依赖boost库,不需要单独编译,在工程的Include目录中添加asio2路径,在源码中#include <asio2/asio2.hpp>即可使用;支持tcp, udp, http, websocket, rpc, ssl, icmp, serial_port;支持可靠UDP(基于KCP),支持SSL;TCP支持各种数据拆包功能(单个字符或字符串或用…...
Uniapp 微信小程序内打开web网页
技术栈:Uniapp Vue3 简介 实际业务中有时候会需要在本微信小程序内打开web页面,这时候可以封装一个路由页面专门用于此场景。 在路由跳转的时候携带路由参数,拼接上web url,接收页面进行参数接收即可。 实现 webview页面 新…...
学习线性表_3
单链表的删除 直接删除即可删除后要free //删除第i个位置的元素 //删除时L是不会变的,所以不需要加引用 bool ListDelect(LinkList L,int i) {//i 1,即删除头指针//拿到要删除结点的前一个结点LinkList p GetElem(L,i-1);if(NULLp){return false;}//拿到要删除的结…...