基于Qt的app开发第八天
写在前面
笔者是一个大一下计科生,本学期的课程设计自命题完成一个督促学生自律的打卡软件,目前已经完成了待办和打卡部分功能,本篇要完成规划板块不需要存储就能实现的功能
需求分析
这一板块内容相比前两个板块还有一些特殊,因为它需要展示两张表,而且每个大规划中的任务数不确定
显式顺序分析:第一个界面视图展示一列列长期规划,然后这一个个规划块里边又有一个一个小任务,且标注完成状态;选中规划块的列点击修改会跳转到第二个界面,然后每个任务块算一行,选中对应行可以修改,点新建可以新加一行,然后跳转到第三个界面;点击新建也是跳转到第二个界面,然后后续就是一样的
实现思路
(1)难点分析
这个项目的难点在于对tableView的操作,tableView可以设置行选中和列选中。这个板块第一个界面设置列选中,第二个界面设置行选中。通过tableView的QstandardItModel的索引来插每行和每列,新增小任务就是在最后一行的上一行插入新任务块
(2)思路梳理
先把控件改成tableView,第一个界面不需要插表头,第二个界面要插表头。然后还是用QString型的QList数据类型来做中介变量,因为这次的时间和打卡板块是一样的,只需要String存储。
实现数据导入和打卡板块几乎是一致的,只需要关注行和列的索引
具体实现
(1)修改控件
修改控件如图,并修改命名
(2)初始化表格
初始化表格就仿照前两个板块即可,包含引用头文件、开模型。
//这个函数的作用是获取并初始化第一个界面的TableView控件
void Plan::GetPlanShowTableView()
{//获取界面中的表格对象QTableView *planShow = ui->planShowTableView;// 设置表格的点击模式为列单选ui->planShowTableView->setSelectionBehavior(QAbstractItemView::SelectColumns); // 选择整列ui->planShowTableView->setSelectionMode(QAbstractItemView::SingleSelection); // 单选模式planShow->setModel(model_1);
}//这个函数的作用是获取并初始化第二个界面的TableView控件
void Plan::GetPlanDecideTableView()
{//获取界面中的表格对象QTableView *planDecide = ui->planDecideTableView;//设置planDecideTableView的表头model_2->setColumnCount(4);model_2->setHorizontalHeaderLabels({"开始时间", "结束时间", "事项", "完成情况"});//设置表格的点击模式为行单选ui->planDecideTableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 选择整行ui->planDecideTableView->setSelectionMode(QAbstractItemView::SingleSelection); // 单选模式planDecide->setModel(model_2);
}
声明变量和包含头文件不重复了,这里附上两个表格的初始化函数
注意要在构造函数中调用这两个函数,笔者刚才跑出来发现没有表格,仔细检查发现是因为构造函数没调用函数
(3)实现新建
这个板块的新建稍微有些复杂,其实也不是复杂,就是实现长度更长了一点,现在笔者来梳理一下传递顺序:
第三个界面里设置起始时间和结束时间,事项以及完成情况——>在第二个界面里的表格出现这么一行,然后在第二个界面可以输入自我评价——>在第一个界面里的表格里出现一列,这一列包含标题、任务块、自我评价。任务块就是第二个界面表格里的内容
由第三个界面传到第二个界面可以使用QString型的动态数组当中介变量,第二个界面传到第一个界面稍稍与前边的板块不同
笔者这里说明一下我的思路:先把标题传回第一个界面,再把自我评价传回第一个界面,然后每个任务块还是使用动态数组传递,每个任务块插入的基准是最后一行的上一行
下边再来分析一下函数实现的顺序:
按钮槽函数自然还是要分成修改和新建功能的if判断
新建功能因为没有原文本,所以直接无脑往回传就可以了。在第三个界面的应用按钮的槽函数里将文本框内容传到第二个界面里,在第二个界面的应用槽函数里将表格里的内容传到第一个界面里
做到第二个界面向第一个界面传递时笔者遇到了问题,因为任务块可能不只有一个,所以需要用一个循环遍历所有行。然后每一行都向第一个界面里传数据
还有另一个问题:因为两个界面里都有应用和修改按钮,笔者最开始觉得设置一个模式选择器就可以,逐步深入的过程中发现还是需要每个界面各一个模式选择器
if(addOrRevise_1==1){//这几行代码的作用是获取第二个界面输入框里的文本QString title=ui->nameInput->text();QString evalution=ui->evaluationInput->toPlainText();int col = model_1->columnCount();model_1->insertColumn(col);QStandardItem *item=new QStandardItem(title);model_1->setItem(0,col,item);item=new QStandardItem(evalution);model_1->setItem(1,col,item);int currentRow=0;//这个循环的作用是把表格里的内容全部放到第一个界面里while(currentRow<model_2->rowCount()){//这几行代码是向中介数组中导入表格数据QModelIndex index = model_2->index(currentRow, 0);QString startTime = index.data().toString();index=model_2->index(currentRow,1);QString endTime=index.data().toString();index=model_2->index(currentRow,2);QString event=index.data().toString();index=model_2->index(currentRow,3);QString isSuccess=index.data().toString();shiftPlanList.append(startTime);shiftPlanList.append(endTime);shiftPlanList.append(event);shiftPlanList.append(isSuccess);//这几行代码的作用是向planShowtableView里添加一个任务块int lastRow = 0;if (model_1->hasChildren()){// 从模型底部向上查找第一个有数据的单元格for (int i = model_1->rowCount() ; i >= 0; i--){if (!model_1->index(i, col).data().isNull()){lastRow = i; // 找到后,插入位置为这一行break;}}}for (int crow = lastRow,cindex=0; crow < lastRow+4; crow++,cindex++){QStandardItem *item = new QStandardItem(shiftPlanList.at(cindex));model_1->setItem(crow, col, item);}QStandardItem *item = new QStandardItem(evalution);model_1->setItem(lastRow+4,col,item);shiftPlanList.clear();currentRow++;}//把这个索引置零,防止干扰后续操作currentRow=0;//这句代码的作用是清空这个数组以及第二个界面的内容,方便下次使用shiftPlanList.clear();if (model_2){// 清空所有行(保留表头)model_2->removeRows(0, model_2->rowCount());}ui->evaluationInput->clear();ui->nameInput->clear();addOrRevise_1=0;}
这是点了第二个界面的应用按钮之后的槽函数
if(addOrRevise_2==1){//这几行代码的作用是获取第三个界面输入框里的文本QString startTime=ui->plannextnext_startTimeInput->text();QString endTime=ui->plannextnext_endTimeInput->text();QString event=ui->plannextnext_eventInput->text();QString isSuccess=ui->plannextnext_isSuccessChoice->currentText();//这几行代码的作用是向中介数组添加数据shiftTaskList.append(startTime);shiftTaskList.append(endTime);shiftTaskList.append(event);shiftTaskList.append(isSuccess);//这几行代码的作用是向planDecidetableView里添加一行int row = model_2->rowCount();model_2->insertRow(row);for (int col = 0; col < 4; col++){QStandardItem *item = new QStandardItem(shiftTaskList.at(col));model_2->setItem(row, col, item);}//这句代码的作用是清空这个数组以及第三个界面的内容,方便下次使用shiftTaskList.clear();ui->plannextnext_startTimeInput->setText("");ui->plannextnext_endTimeInput->setText("");ui->plannextnext_eventInput->setText("");ui->plannextnext_isSuccessChoice->setCurrentText(0);addOrRevise_2=0;}
这是第三个界面的应用按钮的槽函数
核心思路就是上边提到的,在这里着重说一下笔者遇到的困难:
编程前总觉得自己的思路特别完美,但是在没有经验的情况下,考虑难免是不全面的,所以总会出现各种意料之外的问题。笔者对第一个界面的表格操作就是屡屡出错,刚开始先插成一行一行的了 ,后来又把自我评价给覆盖了,后来又出现各种问题。那笔者是怎么解决的呢?就是往进加一些辅助变量,然后再改一下插入逻辑,这个板块越写笔者越觉得像屎山了,现在修改功能还没实现事情就有点超出笔者的控制范围了。
不过没有关系,没有屎山代码的积累就写不出好代码。作为我的处女作,屎山也是很正常的
(4)实现修改
修改功能又比新建功能复杂了一些,因为它还涉及到把表中数据往后边的界面传递。
还是先梳理逻辑:用户按下修改按钮,然后被选中的一列存进第二个界面,标题存在标题输入框,自我评价存在自我评价输入框,每一个任务块一行一行地存,这里肯定也要用一个循环了。然后把这列东西全部删除,点第二个界面的应用按钮后再把这一列加进去,需要注意插入位置一定是选中列;如果在第二个界面用户点击修改,被选中的一行是任务块,然后跳到第三个界面,把这一行的数据存进第三个界面,然后把这行删除,点第三个界面的应用按钮把这一行加进去,插入位置是选中行
//这个函数的作用是修改规划----------------------------------未完成
void Plan::on_revisePlanButton_clicked()
{ui->stackedWidget->setCurrentIndex(1);addOrRevise_1=2;//这个for循环是为了获取当前选中列的最后一行int lastRow = 0;if (model_1->hasChildren()){// 从模型底部向上查找第一个有数据的单元格for (int i = model_1->rowCount() ; i >= 0; i--){if (!model_1->index(i, currentCol).data().isNull()){lastRow = i;break;}}}//这几行代码是把标题和自我评价传到第二个界面里QModelIndex index = model_1->index(0, currentCol);QString title=index.data().toString();ui->nameInput->setText(title);index=model_1->index(lastRow,currentCol);QString evalution=index.data().toString();ui->evaluationInput->setText(evalution);int currentRow=1;//这个while循环的作用是将第一个界面的表格中的每个任务块导入第二个界面的表格中while(currentRow<lastRow){index=model_1->index(currentRow,currentCol);QString startTime = index.data().toString();index=model_1->index(currentRow+1,currentCol);QString endTime=index.data().toString();index=model_1->index(currentRow+2,currentCol);QString event=index.data().toString();index=model_1->index(currentRow+3,currentCol);QString isSuccess=index.data().toString();currentRow+=4;shiftPlanList.append(startTime);shiftPlanList.append(endTime);shiftPlanList.append(event);shiftPlanList.append(isSuccess);//这几行代码的作用是向planDecidetableView里添加一行int taskRow = model_2->rowCount();model_2->insertRow(taskRow);for (int col = 0; col < 4; col++){QStandardItem *item = new QStandardItem(shiftPlanList.at(col));model_2->setItem(taskRow, col, item);}shiftPlanList.clear();}
}
这个函数的作用是点击第一个界面的修改函数之后把所有数据传进第二个界面中
困难倒是没啥,关键是细节要到位,要不然行和列可能会冲突
else if(addOrRevise_1==2){model_1->removeColumn(currentCol);//这几行代码的作用是获取第二个界面输入框里的文本QString title=ui->nameInput->text();QString evalution=ui->evaluationInput->toPlainText();int col = currentCol;model_1->insertColumn(col);QStandardItem *item=new QStandardItem(title);model_1->setItem(0,col,item);item=new QStandardItem(evalution);model_1->setItem(1,col,item);int currentRow=0;//这个循环的作用是把表格里的内容全部放到第一个界面里while(currentRow<model_2->rowCount()){//这几行代码是向中介数组中导入表格数据QModelIndex index = model_2->index(currentRow, 0);QString startTime = index.data().toString();index=model_2->index(currentRow,1);QString endTime=index.data().toString();index=model_2->index(currentRow,2);QString event=index.data().toString();index=model_2->index(currentRow,3);QString isSuccess=index.data().toString();shiftPlanList.append(startTime);shiftPlanList.append(endTime);shiftPlanList.append(event);shiftPlanList.append(isSuccess);//这几行代码的作用是向planShowtableView里添加一个任务块int lastRow = 0;if (model_1->hasChildren()){// 从模型底部向上查找第一个有数据的单元格for (int i = model_1->rowCount() ; i >= 0; i--){if (!model_1->index(i, col).data().isNull()){lastRow = i; // 找到后,插入位置为这一行break;}}}for (int crow = lastRow,cindex=0; crow < lastRow+4; crow++,cindex++){QStandardItem *item = new QStandardItem(shiftPlanList.at(cindex));model_1->setItem(crow, col, item);}QStandardItem *item = new QStandardItem(evalution);model_1->setItem(lastRow+4,col,item);shiftPlanList.clear();currentRow++;}//把这个索引置零,防止干扰后续操作currentRow=0;//这句代码的作用是清空这个数组以及第二个界面的内容,方便下次使用shiftPlanList.clear();if (model_2){// 清空所有行(保留表头)model_2->removeRows(0, model_2->rowCount());}ui->evaluationInput->clear();ui->nameInput->clear();addOrRevise_1=0;}
这个函数和新建唯一的区别就是把原列删除,然后把删除那列插一个新的进去。这段代码没有复用我感觉很屎,但是没办法,前期都是这样做的,为了保持架构的统一,还有让我的思路没那么混乱,我决定就这样继续堆屎了
//这个函数的作用是修改已经存在的规划更细致的部分
void Plan::on_reviseProcessButton_clicked()
{addOrRevise_2=2;ui->stackedWidget->setCurrentIndex(2);//这段代码的作用是将表格中被选中的行的内容依次存进中介数组if (getCurrentRow != -1){for (int col = 0; col < 4; col++){QModelIndex index = model_2->index(getCurrentRow, col);QVariant data = model_2->data(index);shiftTaskList.append(data.toString());}}//这段代码的作用是在界面中设置中介数组中的内容ui->plannextnext_startTimeInput->setText(shiftTaskList[0]);ui->plannextnext_endTimeInput->setText(shiftTaskList[1]);ui->plannextnext_eventInput->setText(shiftTaskList[2]);int isSuccessIndex = ui->plannextnext_isSuccessChoice->findText(shiftTaskList[3]);if (isSuccessIndex != -1){ui->plannextnext_isSuccessChoice->setCurrentIndex(isSuccessIndex);}//要把中介数组清空,方便下次使用shiftTaskList.clear();
}
这是第二个界面的修改按钮的槽函数,作用就是把第二个界面表格中的东西导入第三个界面的输入框中
else if(addOrRevise_2==2){//这段代码的作用是获取当前界面的输入框的内容QString startTime=ui->plannextnext_startTimeInput->text();QString endTime=ui->plannextnext_endTimeInput->text();QString event=ui->plannextnext_eventInput->text();QString isSuccess=ui->plannextnext_isSuccessChoice->currentText();//这段代码的作用是把捕获到的内容再存进中介数组中shiftTaskList.append(startTime);shiftTaskList.append(endTime);shiftTaskList.append(event);shiftTaskList.append(isSuccess);//这个循环的作用是把中介数组的内容传进选中的行中for (int col = 0; col < 4; col++){QStandardItem *item = new QStandardItem(shiftTaskList.at(col));model_2->setItem(getCurrentRow, col, item);}//清空中介数组方便下次使用shiftTaskList.clear();//将界面置空方便下次使用ui->plannextnext_startTimeInput->setText("");ui->plannextnext_endTimeInput->setText("");ui->plannextnext_eventInput->setText("");ui->plannextnext_isSuccessChoice->setCurrentIndex(0);//将选择模式置空,防止干扰下次使用addOrRevise_2=0;}
这个分支就是完成第三个界面的应用,把选中那一行的内容改成第三个界面修改后的内容
篇末总结
做完这个板块笔者又有了很多感悟,也许这是一种厚积薄发?
1.初期编程不难,难的是一直调试改bug,笔者对表格一直不出数据这个问题修改很久
2.人毕竟是有局限性的,一直做下去就会有越来越多的理解,不做的话永远想不到那一步,有些实现逻辑往往是突发奇想的
3.前边的应用按钮槽函数分情况其实是没有必要的,因为修改和新建的区别无非不过就是有没有往后边的界面传数据,这一点在笔者最开始的时候没有意识到,做到后边再梳理逻辑时想明白了
4.中介数组更适合数据集较大时,这样用一个循环比较方便,其实作用并不是很大,那笔者先前认为的天才想法其实也就那样,归根结底是经验不足,对Qt的理解还不到位
5.变量最好不要高一层第一层做同名变量,因为这样很可能分不清,然后出bug找不到;变量能少用就少用,代码复用的时候改的不用那么费劲
6.要注意库函数的传参顺序,可能会出现问题
在这个项目中我的进步很大,越往后做越觉得前期的工作是在堆屎,但是以后我毕竟不会再做C++相关的项目了,所以重构的话可能会是很久以后的事情,现在就往屎山继续堆屎,处女作嘛,屎山很正常,只要我能进步就行了。后续应该会把这个项目传到github上存着,留作纪念
这个板块是目前我事实上做的最难的一个板块,但是花的时间却没有第一个板块多,实现了从无到有之后,难度真的大大减小。
相关文章:

基于Qt的app开发第八天
写在前面 笔者是一个大一下计科生,本学期的课程设计自命题完成一个督促学生自律的打卡软件,目前已经完成了待办和打卡部分功能,本篇要完成规划板块不需要存储就能实现的功能 需求分析 这一板块内容相比前两个板块还有一些特殊,因…...
Springboot之类路径扫描
SpringBoot框架中默认提供的扫描类为:ClassPathBeanDefinitionScanner。 webFlux框架中借助RepositoryComponentProvider扫描符合条件的Repository。 public class ClassPathScanningCandidateComponentProvider{private final List<TypeFilter> includeFilt…...
PNG图片转icon图标Python脚本(简易版) - 随笔
摘要 在网站开发或应用程序设计中,常需将高品质PNG图像转换为ICO格式图标。本文提供一份高效Python解决方案,利用Pillow库实现透明背景完美保留的格式转换。 源码示例 from PIL import Imagedef convert_png_to_ico(png_path, ico_path, size):"…...

数据分析-图2-图像对象设置参数与子图
from matplotlib import pyplot as mp mp.figure(A figure,facecolorgray) mp.plot([0,1],[1,2]) mp.figure(B figure,facecolorlightgray) mp.plot([1,2],[2,1]) #如果figure中标题已创建,则不会新建窗口, #而是将旧窗口设置为当前窗口 mp.figure(A fig…...

查询公网IP地址的方法:查看自己是不是公网ip,附内网穿透外网域名访问方案
本地搭建服务并提供互联网连接时,较为传统的方法是使用公网IP地址。因此,如何查询本地自己是不是公网IP,是必须要掌握的一种技巧。当面对确实无公网IP时,则可以通过内网穿透方案,如nat123网络映射工具,将本…...
MVCC:数据库并发控制的利器
在并发环境下,数据库需要处理多个事务同时访问和修改数据的情况。为了保证数据的一致性和隔离性,数据库需要采用一些并发控制机制。MVCC (Multi-Version Concurrency Control,多版本并发控制) 就是一种常用的并发控制技术,它通过维…...

Redis学习打卡-Day1-SpringDataRedis、有状态无状态
Redis的Java客户端 Jedis 以 Redis 命令作为方法名称,学习成本低,简单实用。Jedis 是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐使用 Jedis 连接池代替Jedis的直连方式。 lettuce Lettuce是基于Netty实现的&am…...
【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀
文章目录 🧳 访问者模式(Visitor Pattern)深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码(游戏物品系统)1. 定义元素与访问者接口2. 实现具体元素类3. 实现具体访问者4. 对象结构管理5. 客户端使用 …...
Shell脚本实践(修改文件,修改配置文件,执行jar包)
1、前言 需要编写一个shell脚本支持 1、修改.so文件名 2、修改配置文件 3、执行jar包 2、代码解析 2.1、修改.so文件名 so_file_dir="/opt/casb/xxx/lib" # 处理.so文件 cd "$so_file_dir" || { echo "错误: 无法进入目录 $so_file_dir"; exit …...
React Native矢量图标全攻略:从入门到自定义iconfont的高级玩法
“你知道吗?在React Native应用中,仅仅通过一行代码就能召唤出上千个精美矢量图标,甚至还能把设计师精心制作的iconfont完美嵌入——但90%的开发者居然还在用图片方案!” 当我第一次发现同事的APP安装包比我的小了2.3MB,仅仅是因为他正确使用了react-native-vector-icons时…...
x-IMU matlab zupt惯性室内定位算法
基于x-IMU的ZUPT(Zero Velocity Update,零速更新)惯性室内定位算法是一种结合了惯性测量单元(IMU)数据和零速检测技术的室内定位方法。该算法通过检测行人静止状态下的零速区间,对惯性导航系统(…...
hbase shell的常用命令
一、hbase shell的基础命令 # 版本号查看 [rootTest-Hadoop-NN-01 hbase]$ ./bin/hbase version HBase 2.4.0 Source code repository git://apurtell-ltm.internal.salesforce.com/Users/apurtell/src/hbase revision282ab70012ae843af54a6779543ff20acbcbb629# 客户端登录 […...
在企业级项目中高效使用 Maven-mvnd
1、引言 1.1 什么是 Maven-mvnd? Maven-mvnd 是 Apache Maven 的一个实验性扩展工具(也称为 mvnd),基于守护进程(daemon)模型构建,目标是显著提升 Maven 构建的速度和效率。它由 Red Hat 推出,通过复用 JVM 进程来减少每次构建时的启动开销。 1.2 为什么企业在构建过…...
iOS瀑布流布局的实现(swift)
在iOS开发中,瀑布流布局(Waterfall Flow)是一种常见的多列不等高布局方式,适用于图片、商品展示等场景。以下是基于UICollectionView实现瀑布流布局的核心步骤和优化方法: 一、实现原理 瀑布流的核心在于动态计算每个…...

Spring Spring Boot 常用注解整理
Spring & Spring Boot 常用注解整理 先理解核心概念:什么是注解(Annotation)?第一部分:IOC(控制反转)和 DI(依赖注入)1. Component2. Service, Repository, Controll…...

c#建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能
# financial_建筑行业 建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能 # 开发背景 软件是给岳阳客户定制开发一款建筑行业流水账财务软件。提供工程签证单、施工日志、人员出勤表等信息记录。 # 财务管理系统功能描述 1.可以自行设置记账科目,做凭…...

让 Cursor 教我写 MCP Client
文章目录 1. 写在最前面2. 动手实现一个 MCP Client2.1 How 天气查询 Client2.1.1 向 Cursor 提问的艺术2.1.2 最终成功展示2.1.3 client 的代码 3. MCP 协议核心之一总结3.1 SSE vs WebSocket 4. 碎碎念5. 参考资料 1. 写在最前面 学习了 MCP Server 的实现后,刚好…...

反射, 注解, 动态代理
文章目录 单元测试什么是单元测试咱们之前是如何进行单元测试的? 有啥问题 ?现在使用方法进行测试优点Junit单元测试的使用步骤删除不需要的jar包总结 反射认识反射、获取类什么是反射反射具体学什么?反射第一步:或者Class对象 获…...

vue vite 无法热更新问题
一、在vue页面引入组件CustomEmployeesDialog,修改组件CustomEmployeesDialog无法热更新 引入方式: import CustomEmployeesDialog from ../dialog/customEmployeesDialog.vue 目录结构: 最后发现是引入import时,路径大小写与目…...
【CustomPagination:基于Vue 3与Element Plus的高效二次封装分页器】
CustomPagination:基于Vue 3与Element Plus的高效二次封装分页器 在现代Web应用开发中,分页是处理大量数据列表时不可或缺的功能。Element Plus等UI库提供了基础的分页组件,但在大型项目中,为了追求极致的用户体验和视觉统一&…...
kafka connect 大概了解
kafka connect Introduction Kafka Connect is the component of Kafka that provides data integration between databases, key-value stores, search indexes, file systems, and Kafka brokers. kafka connect 是一个框架,用来帮助集成其他系统的数据到kafka…...
UniApp 在华为三折叠屏中的适配问题与最佳解决方案(rpx 实战指南)
随着折叠屏设备的普及,如华为 Mate Xs、Mate X3 等多形态设备越来越常见,开发者在 UniApp 项目中遇到的适配问题也变得复杂。本文将聚焦一个关键问题:在三折叠屏设备上,使用 px 单位造成页面显示异常,并给出最推荐的解…...

深度学习中的查全率与查准率:如何实现有效权衡
📌 友情提示: 本文内容由银河易创AI(https://ai.eaigx.com)创作平台的gpt-4-turbo模型辅助生成,旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证,建议读者通过官方文档或实践进一步确认…...
Docker从0到1:入门指南
目录 什么是DockerDocker的核心概念 容器(Container)镜像(Image)镜像层(Image Layers)Dockerfile仓库(Repository)数据卷(Volume)网络(Network) Docker架构Docker安装Docker基本命令实际应用场景Docker生态系统最佳实践常见问题 什么是Docker Docker是一个开源的应用容器引擎…...

Windows玩游戏的时候,一按字符键就显示桌面
最近打赛伯朋克 2077 的时候,不小心按错键了,导致一按字符键就显示桌面。如下: 一开始我以为是输入法的问题(相信打游戏的人都知道输入法和奔跑键冲突的时候有多烦),但是后来解决半天发现并不是。在网上搜…...

Gemini 2.5 Flash和Pro预览版价格以及上下文缓存的理解
Gemini 2.5 Flash和Pro预览版价格 Gemini 2.5 Flash 预览版就是 Google 的最新 AI 大模型,能处理巨量内容。可以免费体验,但有次数和功能上的限制;付费层级才开放全部高级功能。价格也比传统 API 略有不同,尤其在“思考预算”“上…...

vue2 头像上传+裁剪组件封装
背景:最近在进行公司业务开发时,遇到了头像上传限制尺寸的需求,即限制为一寸证件照(宽295像素,高413像素)。 用到的第三方库: "vue-cropper": "^0.5.5" 完整组件代码&…...
unity 鼠标更换指定图标
1.准备两张图 要求图片导入设置如下 将 Texture Type 改为 Cursor 确保 Read/Write Enabled 已勾选 取消勾选 Generate Mip Maps 将 Filter Mode 设为 Point (保持清晰边缘) 将 Compression 设为 None (无压缩) 2.创建脚本,把脚本挂到场景中 ,该…...

AI-02a5a5.神经网络-与学习相关的技巧-权重初始值
权重的初始值 在神经网络的学习中,权重的初始值特别重要。实际上,设定什么样的权重初始值,经常关系到神经网络的学习能否成功。 不要将权重初始值设为 0 权值衰减(weight decay):抑制过拟合、提高泛化能…...

【springcloud学习(dalston.sr1)】Eureka单个服务端的搭建(含源代码)(三)
该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一) 这篇文章主要介绍单个eureka服务端的集群环境是如何搭建的。 通过前面的文章【springcloud学习(dalston.sr1)】…...