QT数据库SQLite:QsqlTableModel使用总结

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

数据库类

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();
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++求20亿内质数的合数“哥德巴赫猜想”

数学领域著名的“哥德巴赫猜想”的大致意思是&#xff1a;任何一个大于2的偶数总能表示为两个素数之和。比如&#xff1a;24519&#xff0c;其中5和19都是素数。本实验的任务是设计一个程序&#xff0c;验证20亿以内的偶数都可以分解成两个素数之和。 输入格式&#xff1a; 输入…

物品识别 树莓派 5 YOLO v5 v8 v10 11 计算机视觉

0. 要实现的效果 让树莓派可以识别身边的一些物品&#xff0c;比如电脑&#xff0c;鼠标&#xff0c;键盘&#xff0c;杯子&#xff0c;行李箱&#xff0c;双肩包&#xff0c;床&#xff0c;椅子等 1. 硬件设备 树莓派 5 raspberrypi.com/products/raspberry-pi-5/树莓派官方摄…

模型训练数据-MinerU一款Pdf转Markdown软件

模型训练数据-MinerU一款Pdf转Markdown软件-说明 简介&#xff1a; MinerU是什么 MinerU是上海人工智能实验室OpenDataLab团队推出的开源智能数据提取工具&#xff0c;专注于复杂PDF文档的高效解析与提取。MinerU能将包含图片、公式、表格等元素的多模态PDF文档转化为易于分析…

51c深度学习~合集9

我自己的原文哦~ https://blog.51cto.com/whaosoft/12750420 #傅里叶特征 (Fourier Feature&#xff09;与核回归 位置编码背后的理论解释 本文探讨了位置编码背后的理论基础&#xff0c;特别是傅里叶特征&#xff08;Fourier Feature&#xff09;与核回归&#xff08;Kern…

数据仓库工具箱—读书笔记01(数据仓库、商业智能及维度建模初步)

数据仓库、商业智能及维度建模初步 记录一下读《数据仓库工具箱》时的思考&#xff0c;摘录一些书中关于维度建模比较重要的思想与大家分享&#x1f923;&#x1f923;&#x1f923; 博主在这里先把这本书"变薄"~有时间的小伙伴可以亲自再读一读&#xff0c;感受一下…

【JVM】JVM基础教程(三)

上一章&#xff1a;【JVM】JVM基础教程&#xff08;二&#xff09;-CSDN博客 目录 运行时数据区 应用场景 程序计数器 程序计数器在运行时会出现内存溢出吗&#xff1f; 栈 IDEA的debug工具查看栈帧的内容 栈帧的组成 局部变量表 关于 this 的内存存储 操作数栈 帧…

如何编译安装系统settings设置应用(5.0.0-Release)

本文介绍如何在OpenHarmony 5.0.0 r版本中修改系统设置应用&#xff0c;并且编译安装到开发板上 开发环境 1.dayu200开发板 2.OpenHarmony 5.0.0r 固件 3.API12 full sdk &#xff08;如果安装full sdk过程中出现报错hvigor ERROR: Cannot find module typescript,请参考 h…

【Unity】Amplify Shader Editor

Amplify Shader Editor (ASE) Amplify Shader Editor&#xff0c;是一个功能强大的基于节点的着色器开发工具&#xff0c;允许开发者在 Unity 中轻松创建和管理复杂的 Shader。 主要功能和特点 基于节点的编辑器&#xff1a; • 提供直观的可视化界面&#xff0c;减少手写 Sh…

Github2024-12-10 Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-12-10统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10HTML项目1Rust项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次关注人…

1.2.3计算机软件

一个完整的计算机系统由硬件和软件组成&#xff0c;用户使用软件&#xff0c;而软件运行在硬件之上&#xff0c;软件进一步的划分为两类&#xff1a;应用软件和系统软件。普通用户通常只会跟应用软件打交道。应用软件是为了解决用户的某种特定的需求而研发出来的。除了每个人都…

ElementEye,网页分析器

介绍 我们经常使用Python写爬虫&#xff0c;爬到网页数据之后&#xff0c;就需要用beautifulSoup进行解析。因为写爬虫并不是我的主营工作&#xff0c;大多数只是用来分析一下想要的数据而已&#xff0c;所以经常会忘记beautifulSoup的用法。 同时&#xff0c;我们总是分析页面…

Qt 联合Halcon配置

文章目录 配置代码窗口绑定 配置 选择添加库 选择外部库 LIBS -LC:/Program Files/MVTec/HALCON-17.12-Progress/lib/x64-win64/ LIBS -lhalconcpp\-lhdevenginecpp\-lhalconINCLUDEPATH C:/Program Files/MVTec/HALCON-17.12-Progress/include DEPENDPATH C:/Program Fil…

图像像素如何排列?是如何存储到diocm里面?读取到内存中是如何存储?

图像像素的排列和存储在DICOM&#xff08;Digital Imaging and Communications in Medicine&#xff0c;医学数字成像和通信&#xff09;文件中遵循特定的标准。DICOM 是一种国际标准&#xff08;ISO 12052&#xff09;&#xff0c;用于处理、存储、打印和传输医学影像信息。 …

深度学习常用损失函数介绍

均方差损失&#xff08;Mean Square Error&#xff0c;MSE&#xff09; 均方误差损失又称为二次损失、L2损失&#xff0c;常用于回归预测任务中。均方误差函数通过计算预测值和实际值之间距离&#xff08;即误差&#xff09;的平方来衡量模型优劣。即预测值和真实值越接近&…

在PowerShell下运行curl命令出现错误:Invoke-WebRequest : 无法处理参数,因为参数名称“u”具有二义性

今天在Windows 11下测试Nanamq的HTTP API&#xff0c;按照其文档输入&#xff1a; curl -i --basic -u admin:public -X GET "http://localhost:8081/api/v4/subscriptions" 结果出现二义性错误&#xff1a; 而且输入curl --help命令想看看参数说明的时候&#xff…

学者观察 | Web 3.0生态治理及其安全——北京交通大学副教授李超

导语 李超教授认为Web 3.0中无论是链上治理还是链下治理都有其优劣。链下治理机制更侧重于社区广泛参与和讨论&#xff0c;过程较为繁琐&#xff0c;但能够形成广泛的社区支持和参与&#xff0c;增强决策的合法性和接受度&#xff1b;链上治理机制通过直接在区块链上执行决策&…

React Router 6的学习

安装react-router-dom npm i react-router-dom 支持不同的路由创建 createBrowserRouter 特点 推荐使用的方式&#xff0c;基于 HTML5 的 History API。支持用户友好的 URL&#xff0c;无需 #。适用于生产环境的绝大多数场景。 适用 使用现代浏览器&#xff0c;支持 pus…

光猫开DMZ教程

本教程以移动光猫未例&#xff0c;具体操作以实际光猫为准 1、登录移动光猫管理后台 打开浏览器&#xff0c;在浏览器地址栏输入移动光猫登录管理地址192.168.1.1或者tplogin.cn 按“回车键”打开登录页面&#xff0c;然后输入路由器管理密码登录。 移动光猫登录页面 超级密…

图像的像素的存储结构:线性结构和二维数组

图像的像素的存储结构 无论是灰度图像还是RGB图像&#xff0c;当它们被读取到内存中时&#xff0c;通常也是以线性结构存储的。 这是因为计算机内存本质上是一维的地址空间&#xff0c;所有数据都是按照线性顺序存储在内存中的。 然而&#xff0c;在程序中处理这些图像时&am…

重庆轨道交通4号线寸滩地铁站自动化监测

1. 项目概述 本次项目位于重庆市轨道交通4号线中江北区寸滩站&#xff0c;轨道交通4号线是中国重庆市第八条开通运营的城市轨道交通&#xff0c;识别色为太阳橙。寸滩地处江北区中部&#xff0c;东与铁山坪街道毗邻&#xff0c;南与南岸区隔江相望&#xff0c;西与江北城中央商…