前端技术
HTML
CSS
Javascript
前端框架和UI库
VUE
ReactJS
AngularJS
JQuery
NodeJS
JSON
Element-UI
Bootstrap
Material UI
服务端和客户端
Java
Python
PHP
Golang
Scala
Kotlin
Groovy
Ruby
Lua
.net
c#
c++
后端WEB和工程框架
SpringBoot
SpringCloud
Struts2
MyBatis
Hibernate
Tornado
Beego
Go-Spring
Go Gin
Go Iris
Dubbo
HessianRPC
Maven
Gradle
数据库
MySQL
Oracle
Mongo
中间件与web容器
Redis
MemCache
Etcd
Cassandra
Kafka
RabbitMQ
RocketMQ
ActiveMQ
Nacos
Consul
Tomcat
Nginx
Netty
大数据技术
Hive
Impala
ClickHouse
DorisDB
Greenplum
PostgreSQL
HBase
Kylin
Hadoop
Apache Pig
ZooKeeper
SeaTunnel
Sqoop
Datax
Flink
Spark
Mahout
数据搜索与日志
ElasticSearch
Apache Lucene
Apache Solr
Kibana
Logstash
数据可视化与OLAP
Apache Atlas
Superset
Saiku
Tesseract
系统与容器
Linux
Shell
Docker
Kubernetes
[确定MySQL服务器版本]的搜索结果
这里是文章列表。热门标签的颜色随机变换,标签颜色没有特殊含义。
点击某个标签可搜索标签相关的文章。
点击某个标签可搜索标签相关的文章。
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 源代码:13033480群共享 无助的时候,我曾读过N遍《金刚经》,讲到《金刚经》,我必须把爱因斯坦先拿来当我的档箭牌,不然,写这么个题目,我可能会被拍死: “如果世界上有一个宗教不但不与科学相违,而且每一次的科学新发现都能够验证她的观点,这就是佛教。”《爱因斯坦文集》,第一卷。 “我不能设想真正的科学家会没有这样深挚的信仰。这情况可以用这样一个形象来比喻:科学没有宗教就象瘸子,宗教没有科学就象瞎子。”------------《爱因斯坦文集》,第三卷,商务印书馆,1979年,第182-183页。 我还要提到我们国家,有位工科出身的领导人,我印象中,他也曾有段时间,每天都读《金刚经》… 先引用一段吧: 所有一切众生之类,若卵生、若胎生、若湿生、若化生、若有色、若无色、若有想、若无想、若非有想非无想,我皆令入无余涅槃而灭度之。如是灭度无量无数无边众生,实无众生得灭度者。何以故?须菩提,若菩萨有我相、人相、众生相、寿者相,即非菩萨。 类是众生之类吗?若化生??若无想??若非有想非无想?? 我不是个无知无欲的佛教徒,写这一段,我是非常非常伤感的,因为今天,我们就要把我们刚刚认识的,刚刚喜欢的,感觉已经有了很深的情感的几个类,几个象人一样可爱的类,给“灭度”掉。 请原谅我的任性,我不知道用这个词到底确切不确切,只是想这么用,就这么用了,原谅我的无知吧…… 这几个类,早已让很多网友不耐烦了,它们是SqlConnection、SqlCommand、SqlDataReader… 让我们,慢慢地,来个《梁山伯与祝英台》中的《十八相送》?? 怕是没有多少人这么有耐心地倾听那悠悠的、凄美的爱情了,我们还是简化一下,分六步吧:…. 一相送,送到try…catch…finally结构中: using System;using System.Data;using System.Data.SqlClient;using System.Configuration;using System.Collections.Generic;using WestGarden.Model;namespace WestGarden.Web{public partial class Default1 : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){IList<CategoryInfo> catogories = new List<CategoryInfo>();string connectionString = ConfigurationManager.ConnectionStrings["NetShopConnString"].ConnectionString;string cmdText = "SELECT CategoryId, Name, Descn FROM Category";SqlCommand cmd = new SqlCommand();SqlConnection conn = new SqlConnection(connectionString);try{cmd.Connection = conn;cmd.CommandType = CommandType.Text;cmd.CommandText = cmdText;conn.Open();SqlDataReader rdr = cmd.ExecuteReader();while (rdr.Read()){CategoryInfo category = new CategoryInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2));catogories.Add(category);}rdr.Close();}finally{conn.Close();}ddlCategories.DataSource = catogories;ddlCategories.DataTextField = "Name";ddlCategories.DataValueField = "CategoryId";ddlCategories.DataBind();} }} 二相送,送到using()结构中: using System;using System.Data;using System.Data.SqlClient;using System.Configuration;using System.Collections.Generic;using WestGarden.Model;namespace WestGarden.Web{public partial class Default2 : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){IList<CategoryInfo> catogories = new List<CategoryInfo>();string connectionString = ConfigurationManager.ConnectionStrings["NetShopConnString"].ConnectionString;string cmdText = "SELECT CategoryId, Name, Descn FROM Category";SqlCommand cmd = new SqlCommand();//简单地说,using()结构等同于前面的try...finally结构,隐式关闭了conn。using(SqlConnection conn = new SqlConnection(connectionString)){cmd.Connection = conn;cmd.CommandType = CommandType.Text;cmd.CommandText = cmdText;conn.Open();SqlDataReader rdr = cmd.ExecuteReader();while (rdr.Read()){CategoryInfo category = new CategoryInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2));catogories.Add(category);}rdr.Close();}ddlCategories.DataSource = catogories;ddlCategories.DataTextField = "Name";ddlCategories.DataValueField = "CategoryId";ddlCategories.DataBind();} }} 三相送,送到通用的数据库访问函数中: using System;using System.Data;using System.Data.SqlClient;using System.Configuration;using System.Collections.Generic;using WestGarden.Model;namespace WestGarden.Web{public partial class Default3 : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){IList<CategoryInfo> catogories = new List<CategoryInfo>();string connectionString = ConfigurationManager.ConnectionStrings["NetShopConnString"].ConnectionString;string cmdText = "SELECT CategoryId, Name, Descn FROM Category";SqlDataReader rdr = ExecuteReader(connectionString, CommandType.Text, cmdText);while (rdr.Read()){CategoryInfo category = new CategoryInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2));catogories.Add(category);}rdr.Close();ddlCategories.DataSource = catogories;ddlCategories.DataTextField = "Name";ddlCategories.DataValueField = "CategoryId";ddlCategories.DataBind();}public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText){SqlCommand cmd = new SqlCommand();SqlConnection conn = new SqlConnection(connectionString);try{cmd.Connection = conn;cmd.CommandType = cmdType;cmd.CommandText = cmdText;conn.Open();//如果创建了 SqlDataReader 并将 CommandBehavior 设置为 CloseConnection,//则关闭 SqlDataReader 会自动关闭此连接SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);return rdr;}catch{conn.Close();throw;}//finally//{// conn.Close();//} }} } 这个通用数据库访问函数可以进一步完善如下: using System;using System.Data;using System.Data.SqlClient;using System.Configuration;using System.Collections.Generic;using WestGarden.Model;namespace WestGarden.Web{public partial class Default4 : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){IList<CategoryInfo> catogories = new List<CategoryInfo>();string connectionString = ConfigurationManager.ConnectionStrings["NetShopConnString"].ConnectionString;string cmdText = "SELECT CategoryId, Name, Descn FROM Category";SqlDataReader rdr = ExecuteReader(connectionString, CommandType.Text, cmdText,null);while (rdr.Read()){CategoryInfo category = new CategoryInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2));catogories.Add(category);}rdr.Close();ddlCategories.DataSource = catogories;ddlCategories.DataTextField = "Name";ddlCategories.DataValueField = "CategoryId";ddlCategories.DataBind();}public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters){SqlCommand cmd = new SqlCommand();SqlConnection conn = new SqlConnection(connectionString);try{//cmd.Connection = conn;//cmd.CommandType = cmdType;//cmd.CommandText = cmdText;//conn.Open();PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);//如果创建了 SqlDataReader 并将 CommandBehavior 设置为 CloseConnection,//则关闭 SqlDataReader 会自动关闭此连接。SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);cmd.Parameters.Clear();return rdr;}catch{conn.Close();throw;}//finally//{// conn.Close();//} }private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms){if (conn.State != ConnectionState.Open)conn.Open();cmd.Connection = conn;cmd.CommandText = cmdText;if (trans != null)cmd.Transaction = trans;cmd.CommandType = cmdType;if (cmdParms != null){foreach (SqlParameter parm in cmdParms)cmd.Parameters.Add(parm);} }} } 因为重点在过程,在结构,代码都比较简单,唯一值得一提的是SqlConnection的关闭问题,在最后比较完善的数据库访问函数中(这是SQLHelper中的源代码),没有使用using()结构,也没有显示关闭,主要原因是调用ExecuteReader方法时,使用了参数 CommandBehavior 并将其设置为 CloseConnection: SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection); 根据MSDN的说法:如果创建了 SqlDataReader 并将 CommandBehavior 设置为 CloseConnection,则关闭 SqlDataReader 会自动关闭此连接。 参考网址:http://msdn.microsoft.com/zh-cn/library/y6wy5a0f(v=vs.80).aspx 版权所有©2012,WestGarden.欢迎转载,转载请注明出处.更多文章请参阅博客http://www.cnblogs.com/WestGarden/ 转载于:https://www.cnblogs.com/WestGarden/archive/2012/06/04/2533560.html 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_33697898/article/details/94471782。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-03-18 20:09:36
89
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 前言 投入同样的时间和精力,你使用不同的途径来成长,收获是不一样的。 关于721法则有两种不同的理解。 理解1: 通过实践,我们可以吸收其中的70%,通过与他人交流,我们可以吸收其中的20%,通过读书和培训,可以吸收其中的10%。 理解2: 一生而言,我们70%的经验来之实践,20%来之与他人交流,10%来之读书和培训。 【----帮助Python学习,以下所有学习资料文末免费领!----】 不管你如何理解,这个721法则都告诉我们:我们都要勇敢地去实践。 实践中我们可以出错,可以不满意,可以有失去,但那都是我们的财富。 不去实践,我们永远站在原地,实践了,那就是希望的开始。 下图是我百度所得: 下面是我用matplotlib画的: 我还有另外一种理解:如果你想有所产出,10%靠运气,20%靠自己,更多的是要靠团队。 我将70%赋予了灰色,这是一种冷色调,代表理性、努力和恒心。其它两种颜色为亮色,表示我们赤诚的心和坚定不移的方向。 如果你感兴趣,可以将下面代码复制到IDLE或者Spyder或者Pycharm,轻轻一点,属于你的图就成了。 第一个图from matplotlib import pyplot as plt 调节图形大小,宽,高plt.figure(figsize=(6,9))定义饼状图的标签,标签是列表labels = [ '实践与经验','交流与反馈','培训与学习']每个标签占多大,会自动去算百分比sizes = [70,20,10]colors = ['red','yellowgreen','lightskyblue']colors = ['gray','00FFFF','FF1493']灰、粉、蓝绿将某部分爆炸出来, 使用括号,将第一块分割出来,数值的大小是分割出来的与其他两块的间隙explode = (0.05,0.05,0)patches,l_text,p_text = plt.pie(sizes,explode=explode,labels=labels,colors=colors,labeldistance = 1.1,autopct = '%3.1f%%',shadow = False,startangle = 90,pctdistance = 0.6)labeldistance,文本的位置离远点有多远,1.1指1.1倍半径的位置autopct,圆里面的文本格式,%3.1f%%表示小数有三位,整数有一位的浮点数shadow,饼是否有阴影startangle,起始角度,0,表示从0开始逆时针转,为第一块。一般选择从90度开始比较好看pctdistance,百分比的text离圆心的距离patches, l_texts, p_texts,为了得到饼图的返回值,p_texts饼图内部文本的,l_texts饼图外label的文本改变文本的大小方法是把每一个text遍历。调用set_size方法设置它的属性for t in l_text:t.set_size(25)for t in p_text:t.set_size(20) 设置x,y轴刻度一致,这样饼图才能是圆的plt.axis('equal')plt.legend(loc="upper left",frameon=False,fontsize=20,borderaxespad=-5)plt.title('721法则', y=-0.1,fontsize=30,loc="center")plt.savefig("721法则.png")plt.show() 下图还是我画的,当然,没有上面那个美观。 第二个图import matplotlib.pyplot as pltplt.rcParams['font.family']='SimHei'plt.figure(figsize=(6, 9))labels = '实践与经验','交流与反馈','培训与学习'sizes = [70.0,20.0,10.0]explode = (0.1,0,0)colors = ['gray','00FFFF','FF1493']plt.pie(sizes,explode=explode,labels=labels,colors=colors,labeldistance=1.1,\autopct='%d%%',shadow=True,counterclock=False)plt.legend(loc="upper left",frameon=False,fontsize=18,borderaxespad=-5)plt.axis('equal')plt.title('721法则', y=-0.1,fontsize=18)plt.savefig("721法则.png")plt.show() 结论:我们不但要会画,还要学着画得尽可能美,实践是唯一的途径。 Python入门教程 如果你现在还是不会Python也没关系,下面我会给大家免费分享一份Python全套学习资料, 包含视频、源码、课件,希望能帮到那些不满现状,想提升自己却又没有方向的朋友,可以和我一起来学习交 流。 ① Python所有方向的学习路线图,清楚各个方向要学什么东西 ② 600多节Python课程视频,涵盖必备基础、爬虫和数据分析 ③ 100多个Python实战案例,含50个超大型项目详解,学习不再是只会理论 ④ 20款主流手游迫解 爬虫手游逆行迫解教程包 ⑤ 爬虫与反爬虫攻防教程包,含15个大型网站迫解 ⑥ 爬虫APP逆向实战教程包,含45项绝密技术详解 ⑦ 超300本Python电子好书,从入门到高阶应有尽有 ⑧ 华为出品独家Python漫画教程,手机也能学习 ⑨ 历年互联网企业Python面试真题,复习时非常方便 👉Python学习视频600合集👈 观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。 👉实战案例👈 光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。 👉100道Python练习题👈 检查学习结果。 👉面试刷题👈 资料领取 上述这份完整版的Python全套学习资料已经上传CSDN官方,朋友们如果需要可以微信扫描下方CSDN官方认证二维码输入“领取资料” 即可领取 好文推荐 了解python的前景:https://blog.csdn.net/weixin_49891576/article/details/127187029 了解python的兼职:https://blog.csdn.net/weixin_49891576/article/details/127125308 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_49891576/article/details/130861900。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-06-04 23:38:21
105
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 今天,正运动小助手给大家分享一下运动控制器之ZMC420SCAN控制器如何操作进行双振镜运动。 一ZMC420SCAN硬件介绍 1.功能介绍 ZMC420SCAN总线控制器支持ECAT/RTEX总线连接,支持最多达20轴运动控制,支持直线插补、任意圆弧插补、空间圆弧、螺旋插补、电子凸轮、电子齿轮、同步跟随、虚拟轴设置等;采用优化的网络通讯协议可以实现实时的运动控制。ZMC420SCAN总线控制器支持脉冲轴/总线轴/振镜轴混合插补。 ZMC420SCAN系列运动控制器支持以太网,RS232通讯接口和电脑相连,接收电脑的指令运行,可以通过CAN总线去连接各个扩展模块,从而扩展输入输出点数或运动轴。 ZMC420SCAN系列运动控制卡的应用程序可以使用VC,VB,VS,C++,C等软件来开发,程序运行时需要动态库zmotion.dll。调试时可以把ZDevelop软件同时连接到控制器,从而方便调试、方便观察。 2.硬件接口 3.振镜控制过程 激光振镜是一种专门用于激光加工领域的特殊的运动器件,激光振镜头内包含的主要元件是激光发生器,两个电机和两个振镜片,它靠两个电机分别控制两个振镜片X和Y反射激光,形成XY平面的运动,这两个电机使用控制器上的振镜轴接口控制。 激光振镜不同于一般的电机,激光振镜具有非常小的惯量,且在运动的过程中负载非常小,只需要带动反射镜片,系统的响应非常快。 ZMC420SCAN支持XY2-100振镜协议,支持运动控制与振镜联合插补运动。 上位机通过网口与控制器相连,通过XY2-100振镜协议进行控制振镜轴的运动,通过总线协议或者脉冲模式控制伺服轴运动。 使用ZMC420SCAN控制器的振镜轴接口连接激光振镜头,每个振镜轴接口内包含两路振镜通道信号,分别控制振镜片X、Y的偏转,从而控制了激光打到工件的位置。 4. 控制器PWM模拟量介绍 ZMC420SCAN的外部通用输出口0-11都具有PWM输出功能,PWM 输出受正常输出功能的控制,只有输出口状态ON的时候PWM才能实际输出,这样可以用来控制激光能量。 ZMC420SCAN控制器存在两路模拟量输入输出,可进行控制激光器能量输出,模拟量精度为12位。(DA采用了内部电源) 5.控制器基本信息 轴0-3为普通脉冲轴,振镜0为轴4、轴5控制振镜XY,振镜1为轴6、轴7控制XY。 二C++ 进行振镜+运动控制开发 1. 新建MFC项目并添加函数库 (1)在VS2015菜单“文件”→“新建”→ “项目”,启动创建项目向导。 (2)选择开发语言为“Visual C++”和程序类型“MFC应用程序”。 (3)点击下一步即可。 (4)选择类型为“基于对话框”,下一步或者完成。 (5)找到厂家提供的光盘资料,路径如下(64位库为例)。 A.进入厂商提供的光盘资料找到“8.PC函数”文件夹,并点击进入。 B.选择“函数库2.1”文件夹。 C.选择“Windows平台”文件夹。 D.根据需要选择对应的函数库这里选择64位库。 E.解压C++的压缩包,里面有C++对应的函数库。 F.函数库具体路径如下。 (6)将厂商提供的C++的库文件和相关头文件复制到新建的项目里面。 (7)在项目中添加静态库和相关头文件。 A.先右击项目文件,接着依次选择:“添加”→“现有项”。 B.在弹出的窗口中依次添加静态库和相关头文件。 (8)声明用到的头文件和定义控制器连接句柄。 至此项目新建完成,可进行MFC项目开发。 2.查看PC函数手册,熟悉相关函数接口 (1)PC函数手册也在光盘资料里面,具体路径如下:“光盘资料\8.PC函数\函数库2.1\ZMotion函数库编程手册 V2.1.pdf” (2)链接控制器,获取链接句柄。 ZAux_OpenEth()接口说明: (3)振镜运动接口。 为振镜运动单独封装了一个运动接口,使用movescanabs指令进行运动,采用FORCE_SPEED参数设置运动过程中的速度,运动过程中基本不存在加减速过程,支持us级别的时间控制。 3. MFC开发控制器双振镜运动例程 (1)例程界面如下。 (2) 链接按钮的事件处理函数中调用链接控制器的接口函数ZAux_OpenEth(),与控制器进行链接,链接成功后启动定时器1监控控制器状态。 //网口链接控制器void CSingle_move_Dlg::OnOpen(){char buffer[256]; int32 iresult;//如果已经链接,则先断开链接if(NULL != g_handle){ZAux_Close(g_handle);g_handle = NULL;}//从IP下拉框中选择获取IP地址GetDlgItemText(IDC_IPLIST,buffer,255);buffer[255] = '\0';//开始链接控制器iresult = ZAux_OpenEth(buffer, &g_handle);if(ERR_SUCCESS != iresult){g_handle = NULL;MessageBox(_T("链接失败"));SetWindowText("未链接");return;}//链接成功开启定时器1SetWindowText("已链接");SetTimer( 1, 100, NULL ); } (3)通过定时器监控控制器状态 。 void CSingle_move_Dlg::OnTimer(UINT_PTR nIDEvent) {// TODO: Add your message handler code here and/or call defaultif(NULL == g_handle){MessageBox(_T("链接断开"));return ;}if(1 == nIDEvent){CString string;float position = 0;ZAux_Direct_GetDpos( g_handle,m_nAxis,&position); //获取当前轴位置string.Format("振镜X1轴位置:%.2f", position );GetDlgItem( IDC_CURPOS )->SetWindowText( string );float NowSp = 0;ZAux_Direct_GetVpSpeed( g_handle,m_nAxis,&NowSp); //获取当前轴速度string.Format("振镜X1轴速度:%.2f", NowSp );GetDlgItem( IDC_CURSPEED)->SetWindowText( string );ZAux_Direct_GetDpos(g_handle, m_nAxis+1, &position); //获取当前轴位置string.Format("振镜Y1轴位置:%.2f", position);GetDlgItem(IDC_CURPOS2)->SetWindowText(string);ZAux_Direct_GetVpSpeed(g_handle, m_nAxis+1, &NowSp); //获取当前轴速度string.Format("振镜Y1轴速度:%.2f", NowSp);GetDlgItem(IDC_CURSPEED2)->SetWindowText(string);ZAux_Direct_GetDpos(g_handle, m_nAxis + 2, &position); //获取当前轴位置string.Format("振镜X2轴位置:%.2f", position);GetDlgItem(IDC_CURPOS3)->SetWindowText(string);NowSp = 0;ZAux_Direct_GetVpSpeed(g_handle, m_nAxis + 2, &NowSp); //获取当前轴速度string.Format("振镜X2轴速度:%.2f", NowSp);GetDlgItem(IDC_CURSPEED3)->SetWindowText(string);ZAux_Direct_GetDpos(g_handle, m_nAxis + 3, &position); //获取当前轴位置string.Format("振镜Y2轴位置:%.2f", position);GetDlgItem(IDC_CURPOS4)->SetWindowText(string);ZAux_Direct_GetVpSpeed(g_handle, m_nAxis + 3, &NowSp); //获取当前轴速度string.Format("振镜Y2轴速度:%.2f", NowSp);GetDlgItem(IDC_CURSPEED4)->SetWindowText(string);int status = 0; ZAux_Direct_GetIfIdle(g_handle, m_nAxis,&status); //判断当前轴状态if (status == -1){GetDlgItem( IDC_CURSTATE )->SetWindowText( "当前状态:停 止" );}else{GetDlgItem( IDC_CURSTATE )->SetWindowText( "当前状态:运动中" );} }CDialog::OnTimer(nIDEvent);} (4)通过启动按钮的事件处理函数获取编辑框的移动轨迹,并设置振镜轴参数操作振镜轴运动。 void CSingle_move_Dlg::OnStart() //启动运动{if(NULL == g_handle){MessageBox(_T("链接断开状态"));return ;}UpdateData(true);//刷新参数int status = 0; ZAux_Direct_GetIfIdle(g_handle, m_nAxis,&status); //判断当前轴状态 if (status == 0) //已经在运动中{ return;} //设定轴类型 1-脉冲轴类型 for (int i = 4; i < 8; i++){ZAux_Direct_SetAtype(g_handle, i, m_Atype);ZAux_Direct_SetMerge(g_handle,i,1);//设置脉冲当量ZAux_Direct_SetUnits(g_handle, i, m_units);//设定速度,加减速ZAux_Direct_SetLspeed(g_handle, i, m_lspeed);ZAux_Direct_SetSpeed(g_handle, i, m_speed);ZAux_Direct_SetForceSpeed(g_handle, i, m_speed);ZAux_Direct_SetAccel(g_handle, i, m_acc);ZAux_Direct_SetDecel(g_handle, i, m_dec);//设定S曲线时间 设置为0表示梯形加减速 ZAux_Direct_SetSramp(g_handle, i, m_sramp);}//使用MOVESCANABS运动int axislist[2] = { 4,5 };float dposlist[2] = { 0,0 };ZAux_MoveScanAbs(2, axislist, dposlist);CString str;GetDlgItem(IDC_EDIT_POSX1)->GetWindowText(str);float dbx = atof(str);GetDlgItem(IDC_EDIT_POSY1)->GetWindowText(str);float dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);GetDlgItem(IDC_EDIT_POSX2)->GetWindowText(str);dbx = atof(str);GetDlgItem(IDC_EDIT_POSY2)->GetWindowText(str);dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);GetDlgItem(IDC_EDIT_POSX3)->GetWindowText(str);dbx = atof(str);GetDlgItem(IDC_EDIT_POSY3)->GetWindowText(str);dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);GetDlgItem(IDC_EDIT_POSX4)->GetWindowText(str);dbx = atof(str);GetDlgItem(IDC_EDIT_POSY4)->GetWindowText(str);dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);//第二个振镜运动//使用MOVESCANABS运动axislist[0] = 6;axislist[1] = 7;dposlist[0] = 0;dposlist[1] = 0;ZAux_MoveScanAbs(2, axislist, dposlist);GetDlgItem(IDC_EDIT_POSX5)->GetWindowText(str);dbx = atof(str);GetDlgItem(IDC_EDIT_POSY5)->GetWindowText(str);dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);GetDlgItem(IDC_EDIT_POSX6)->GetWindowText(str);dbx = atof(str);GetDlgItem(IDC_EDIT_POSY6)->GetWindowText(str);dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);GetDlgItem(IDC_EDIT_POSX7)->GetWindowText(str);dbx = atof(str);GetDlgItem(IDC_EDIT_POSY7)->GetWindowText(str);dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);GetDlgItem(IDC_EDIT_POSX8)->GetWindowText(str);dbx = atof(str);GetDlgItem(IDC_EDIT_POSY8)->GetWindowText(str);dby = atof(str);dposlist[0] = dbx;dposlist[1] = dby;ZAux_MoveScanAbs(2, axislist, dposlist);UpdateData(false); } (5) 通过断开按钮的事件处理函数来断开与控制卡的连接。 void CSingle_move_Dlg::OnClose() //断开链接{// TODO: Add your control notification handler code hereif(NULL != g_handle){KillTimer(1); //关定时器KillTimer(2);ZAux_Close(g_handle);g_handle = NULL;SetWindowText("未链接");} } (6)通过坐标清零按钮的事件处理函数移动振镜轴回零到中心零点位置,不直接使用dpos=0,修改振镜轴坐标。 void CSingle_move_Dlg::OnZero() //清零坐标{if(NULL == g_handle){MessageBox(_T("链接断开状态"));return ;}// TODO: Add your control notification handler code hereint axislist[2] = { 4,5 };float dposlist[2] = { 0 };ZAux_Direct_MoveAbs(g_handle,2,axislist,dposlist); //设置运动回零点} 三调试与监控 编译运行例程,同时通过ZDevelop软件连接控制器对控制器状态进行监控 。 ZDevelop软件连接控制器监控控制器的状态,查看振镜轴对应参数,并可搭配示波器检测双振镜轨迹。 设置振镜轴运动,首先需要将轴类型配置成21振镜轴类型,并对应配置振镜轴的速度加减速等参数才可操作振镜进行运动。 通过ZDevelop软件的示波器监控双振镜运动运行轨迹。 视频演示。 开放式激光振镜+运动控制器(六)-双振镜运动 本次,正运动技术开放式激光振镜+运动控制器(六):双振镜运动,就分享到这里。 更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师:400-089-8936。 本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_57350300/article/details/123402200。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-12-04 17:33:09
338
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 望京是北京除中关村之外最大的互联网公司聚集地,这里云集了众多一线二线互联网大厂,独角兽公司,今天这篇文章推荐16家公司。正好金九银十求职黄金季节,大家可以作为参考。 阿里巴巴集团 阿里巴巴入驻望京让望京的互联网氛围更加浓厚。阿里系的企业非常多,比如阿里云、天猫、高德、阿里体育、阿里文娱、阿里健康、本地生活、阿里妈妈、达摩院、考拉、阿里影业等。 阿里的福利待遇没的说,七险一金、一般能拿到16薪、住房公积金全额缴纳、节日礼物等。 面试比较难,八股文和算法必须要多准备。 招聘的岗位也是非常多的,比如JAVA、大数据、算法等,下图从BOSS上截取的: 蚂蚁金服不在望京,在环球金融中心。 美团 美团是望京第二大互联网公司,技术氛围浓厚。事业部很多,包括酒店事业部、闪购、美团金融、优选事业部、美团买菜等。 美团的福利常常被叫做白开水福利,不过比普通公司还是要好一些,六险一金、15薪、餐补、下午茶等。 面试比阿里容易一些,不过算法和八股文也是必须要准备的。 常年招聘,岗位很多,下面岗位来自BOSS: Lazada 东南亚头部电商,而且业务还囊括了娱乐、金融和物流,业务主要服务于东南亚。工作地点在朝阳区阿里中心。 福利待遇包括六险一金、年终奖、股权、餐补交通补等。 主要招聘岗位包括java开发、游戏开发、前端、UI等。 bilibili bilibili也是非常不错的一家互联网公司,总部在上海,北京的工作地点在朝阳区东煌大厦10层。截至2021年第一季度,B站月活用户达2.23亿 福利待遇比较完备,包括六险一金、餐补、全勤奖、下午茶、股权等。 招聘岗位包括游戏服务端开发、java开发、C++开发、TA、linux内核开发等。从招聘岗位来看,java 开发并不是bilibili的热门岗位。 每日优鲜 每日优鲜近几年的发展是非常快速的,也是一家非常值得加入的公司。工作地点在万科时代中心。 工作强度比较大,工作内容也比较有挑战,晋升也比较快。建议想在技术上成长的朋友们加入。 福利待遇包括六险一金,股票期权。 招聘岗位以java为主,架构、资深、中高级都有。 BIGO BIGO主要业务在音视频领域,主要产品有Bigo Live、Likee、Hello,目前全球月活用户近4亿,产品和服务覆盖超过150个国家和地区。 福利待遇也是非常不错的,六险一金、年终奖、住房补贴、股票期权等。 主要招聘岗位包括JAVA、音视频领域后端开发。 coupang 韩国电商平台,总部在首尔,成立于2010年,是一家成熟的老牌公司,在2021年3月上市。目前国内研发团队主要在上海,在北京也有研发团队。工作地点在颐堤港。 coupang工作强度不大,不加班不内卷。福利待遇也是很不错的,包括六险一金、餐补、补充公积金、节日福利等。 招聘岗位主要包括JAVA、IOS、搜索工程师、全栈工程师等。 面试难度比较大,前后包括五轮以上面试,第一轮是电话面试,后面线程面试会有手写代码环节。 水滴公司 水滴这两年发展很快,工作地点在望京科技园。 福利待遇方面,属于互联公司中等偏上的水平,包括六险一金、补充公积金、免费健身房等。 招聘岗位JAVA居多,各种级别的都有,还有一些中间件的岗位。 据面试过水滴的求职者反馈,面试很难,对基础要求高,可能会问一些平时不太关注的非常细的问题。 keep 爱运动的小伙伴相信都熟悉keep这款软件,目前keep的用户量已经破3亿。工作地点在万科时代中心。 薪资待遇行业中等,不过该有的服务也基本都有,包括六险一金、年终奖、股权等。 招聘岗位以java为主,各种级别都有。 雪球 国内知名的投资交流平台,2020年底完成1.2亿美元 E 轮融资,发展潜力巨大。工作地点在融新科技中心。 福利待遇在行业内属于中等水平,包括六险一金、年终奖、餐补、零食下午茶等。 招聘岗位以java为主,还有搜索研发、全栈开发等。 陌陌 陌生人社交平台,深受年轻人喜爱,18年陌陌全资收购了探探,规模进一步扩大,目前月活用户在1亿+,出海业务也做的非常好。 福利待遇属于行业中等偏上,互联网有的福利基本都有,包括六险一金、年终奖等。 招聘岗位很多,包括java、中间件、推荐算法、自然语言处理、安全、游戏开发、IOS等。 面试难度中等,会有手写sql、算法、linux命令的环节。 松果出行 松果出行主要业务是构建国内县域城市交通出行网络,目前主要是共享电单车和共享新能源汽车服务。目前业务已经覆盖全国21个省,5000个县。 福利待遇属于行业中等,五险一金、年终奖等,没有补充医疗保险。 招聘岗位很多,以JAVA为主,各种级别都有。也有物联网、传感器硬件相关的岗位。 小桔科技 目前研发团队主要做推荐、搜索系统,注册地在大连。 福利待遇行业中等,五险一金、年终奖,没有补充医疗保险。 招聘岗位包括JAVA、PHP、搜索算法、前端、数仓等。 理想汽车 智能电动车品牌,这两年在行业内名气比较大。 福利待遇行业中等偏上,六险一金、交通补贴等。 招聘岗位很多,以JAVA为主,各种级别都有。另外也招聘PaaS平台研发、搜索、车载语音、大数据等。 参加过理想汽车面试的同学反馈面试体验不太好,面试官没有耐心,给大家一个参考。 狮桥 智慧物流+普惠金融融资租赁业务。 福利待遇中等偏下,五险一金、年终奖,没有补充医疗保险。 招聘岗位主要是JAVA开发。 领创集团 海外金融业务,主要做印度市场。 福利待遇中等偏下,六险一金,年终奖,工作节奏慢。 招聘岗位主要是JAVA,招聘岗位主要是java。 面试过的同学反馈体验比较好,面试官比较nice,有手写代码环节。 总结 今天主要推荐了望京的16家值得加入的互联网公司,事实上,望京区域的互联网公司和其他科技公司至少有几百家,由于个人精力有限,主要梳理了业界比较知名和自己熟悉的公司。相信还有好多非常不错的公司值得加入,欢迎大家跟我交流讨论。 欢迎关注个人公众号,一起学习进步 本篇文章为转载内容。原文链接:https://blog.csdn.net/zjj2006/article/details/121412370。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-01-11 22:59:19
529
转载
.net
...需要在程序中使用这个服务。按照传统的做法,可能会直接在类内部实例化: csharp public class Worker { private readonly IService _service = new Service(); public void Execute() { _service.DoWork(); } } 这种方式看起来没什么问题,但实际上隐藏着巨大的隐患。比如,如果你需要替换Service为其他实现(比如MockService),你就得修改Worker类的代码。这违背了开闭原则。 于是,我们引入了依赖注入框架,比如Microsoft的Microsoft.Extensions.DependencyInjection。让我们看看如何正确配置。 --- 3. 正确配置 DI容器的正确姿势 首先,你需要注册服务。比如,在Program.cs文件中: csharp using Microsoft.Extensions.DependencyInjection; var services = new ServiceCollection(); services.AddTransient(); var serviceProvider = services.BuildServiceProvider(); 这里的关键点在于Transient这个词。它表示每次请求时都会生成一个新的实例。对了,还有别的选择呢,比如说 Scoped——在一个作用域里大家用同一个实例,挺节省资源的;再比如 Singleton——在整个应用跑着的时候大家都用一个“独苗”实例,从头到尾都不换。选择合适的生命周期很重要,否则可能会导致意想不到的行为。 接下来,我们可以通过依赖注入获取实例: csharp public class Worker { private readonly IService _service; public Worker(IService service) { _service = service; } public void Execute() { _service.DoWork(); } } 在这个例子中,Worker类不再负责创建IService的实例,而是由DI容器提供。这种解耦的方式让代码更加灵活。 --- 4. 配置错误 常见的坑 然而,现实总是比理想复杂得多。以下是一些常见的DI配置错误,以及它们可能带来的后果。 4.1 注册类型时搞错了 有时候我们会不小心把类型注册错了。比如: csharp services.AddTransient(); // 想注册MockService,却写成了Service 结果就是,无论你在代码中怎么尝试,拿到的永远是Service而不是MockService。其实这个坑挺容易被忽略的,毕竟编译器又不报错,一切都看起来风平浪静,直到程序跑起来的时候,问题才突然冒出来,啪叽一下给你整一个大 surprise! 我的建议是,尽量使用常量或者枚举来定义服务名称,这样可以减少拼写错误的风险: csharp public static class ServiceNames { public const string MockService = "MockService"; public const string RealService = "RealService"; } services.AddTransient(ServiceNames.MockService, typeof(MockService)); 4.2 生命周期设置不当 另一个常见的问题是生命周期设置错误。比如说,你要是想弄个单例服务,结果不小心把它设成了 Transient,那每次调用的时候都会新生成一个实例。这就好比你本来想让一个人负责一件事,结果每次都换个人来干,不仅效率低得让人崩溃,搞不好还会出大乱子呢! csharp // 错误示范 services.AddTransient(); // 正确示范 services.AddSingleton(); 记住,单例模式适用于那些无状态或者状态不重要的场景。嘿,想象一下,你正在用一个数据库连接池这种“有状态”的服务,要是把它搞成单例模式,那可就热闹了——多个线程或者任务同时去抢着用它,结果就是互相踩脚、搞砸事情,什么竞争条件啦、数据混乱啦,各种麻烦接踵而至。就好比大家伙儿都盯着同一个饼干罐子,都想伸手拿饼干,但谁也没个规矩,结果不是抢得太猛把罐子摔了,就是谁都拿不痛快。所以啊,这种情况下,还是别让单例当这个“独裁者”了,分清楚责任才靠谱! 4.3 忘记注册依赖 有时候,我们可能会忘记注册某些依赖项。比如: csharp public class SomeClass { private readonly IAnotherService _anotherService; public SomeClass(IAnotherService anotherService) { _anotherService = anotherService; } } 如果IAnotherService没有被注册到DI容器中,那么在运行时就会抛出异常。为了避免这种情况,你可以使用AddScoped或AddTransient来确保所有依赖都被正确注册。 --- 5. 探讨与总结 通过今天的讨论,我们可以看到,虽然依赖注入能够极大地提高代码的质量和可维护性,但它并不是万能的。设置搞错了,那可就麻烦大了,小到一个单词拼错了,大到程序跑偏、东西乱套,什么幺蛾子都可能出现。 我的建议是,在使用DI框架时要多花时间去理解和实践。不要害怕犯错,因为正是这些错误教会了我们如何更好地编写代码。同时,也要学会利用工具和日志来帮助自己排查问题。 最后,我想说的是,编程不仅仅是解决问题的过程,更是一个不断学习和成长的过程。希望大家能够在实践中找到乐趣,享受每一次成功的喜悦! 好了,今天的分享就到这里啦,如果你有任何疑问或者想法,欢迎随时留言交流哦!😄
2025-05-07 15:53:50
40
夜色朦胧
Apache Lucene
...验到最棒、最快的搜索服务,让每一次敲击键盘都能带来惊喜! --- 以上内容不仅涵盖了理论解释与代码实现,还穿插了人类在面对技术难题时的思考与探讨,旨在提供一种更加贴近实际应用、充满情感与主观色彩的技术解读方式。
2024-07-25 00:52:37
391
青山绿水
Mahout
...自动化审批流程,提高服务效率。 未来趋势与展望 随着5G、物联网、边缘计算等新技术的普及,实时光流分析与AI在金融领域的应用将更加广泛。未来,金融机构将能够实时处理海量的物联网设备产生的数据,实现智能资产管理、个性化金融服务等创新应用。同时,随着法律法规的完善和技术标准的统一,实时光流分析与AI在金融行业的应用将更加规范和成熟,为金融市场的健康发展提供坚实的技术支撑。 实时光流分析与AI在金融领域的深度融合,正引领着金融科技创新的新潮流,不仅推动了金融行业的数字化转型,也为全球经济的可持续发展注入了新的活力。随着技术的不断进步与应用场景的不断拓展,这一领域的发展前景无疑充满了无限可能。
2024-09-06 16:26:39
59
月影清风
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 首先感谢以下大佬提供帮助 斗鱼视频下载-> https://www.jianshu.com/p/feccccb097be 批量合并处理B站视频->https://www.wandouip.com/t5i227224/ You-Get->https://you-get.org/ 思路 首先打开了PC端斗鱼视频一个链接:https://v.douyu.com/show/0Q8mMY0xXDL749Ad 发现一个参数在链接中 0Q8mMY0xXDL749Ad 通过抓包发现了一个很重要的文件:playlist.m3u8 里面包含了数个 .ts 的网络地址; .ts 文件是可以播放的视频片段; 发现 可以通过合并 .ts 片段可以得到完整视频; 出现一个问题:playlist.m3u8 怎么获取? 发现:https://v.douyu.com/api/stream/getStreamUrl 可以获取 playlist.m3u8 文件地址; 需要POST传入一些参数才行,发现: sign 参数是一种签名,一般通过JS生成,找了半天没有方法生成 sign 参数; 通过查阅大佬文献发现:手机端的斗鱼视频有接口可以直接获取 playlist.m3u8 文件地址,成功越过 sign 签名防线; 手机端斗鱼视频链接:https://vmobile.douyu.com/show/0Q8mMY0xXDL749Ad 通过抓包发现:https://vmobile.douyu.com/video/getInfo?vid=0Q8mMY0xXDL749Ad; 这就解决了playlist.m3u8 文件获取问题:json[‘data’][‘video_url’] 第一个难题解决!!; 综上所述,整理一下具体采集流程: 获取vid = 0Q8mMY0xXDL749Ad (就是链接中的参数); 通过 https://vmobile.douyu.com/video/getInfo?vid=0Q8mMY0xXDL749Ad 获取 playlist.m3u8 文件地址; 解析 playlist.m3u8 文件提取所有 .ts文件; 下载所有 .ts 文件; 合并 .ts 成视频文件输出; Python实现 不要开启线程池,因为会有一些问题 app.py config 中可以配置 import requestsimport reimport jsonimport timeimport pymongoimport psutilfrom hashlib import md5from moviepy.editor import from multiprocessing import Pool基本配置config = {'UID':'gKpdxKRWXwaW',用户ID'CID':104,栏目ID'TYPE':1, 1=>按用户id采集列表,2=>按栏目ID采集列表'TIME_START':1,起始时间'TIME_ENT':500,结束时间'PAGE_START':1,起始页'PAGE_END':10,结束页'TIME_GE':0,每个下载间隔时间'POOL':False,是否开启线程池'CHECKID':True, True 过滤已经下载过的视频 False 不过滤'FILE_PATH':'F:/ceshi/',下载目录,【会自动创建文件夹】'TS_PATH':'F:/ceshi/download/',缓存文件目录,【会自动创建文件夹】'DB_URL':'localhost',数据库地址'DB_NAME':'douyu',数据库名称''DB_TABLE':'douyu'数据库表}MongoDB初始化client = pymongo.MongoClient(config['DB_URL'])mango_db = client[config['DB_NAME']]MongoDB存储def save_to_mango(result):if mango_db[config['DB_TABLE']].insert_one({'vid':result}):print('成功存储到MangoDB')return Truereturn FalseMongoDB验证重复def check_to_mongo(vid):count = mango_db[config['DB_TABLE']].find({'vid':vid}).count()if count==0:return Falsereturn True删除文件def del_file(page):if os.path.exists(page): 删除文件,可使用以下两种方法。os.remove(page) os.unlink(my_file)else:print('no such file:%s' % page)循环列表删除文件def loop_del_file(arr):for item in arr:del_file(item)请求器def get_content_requests(url):headers = {}headers['user-agent']='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'headers['cookie'] = 'dy_did=07f83a57d1d2e22942e0883200001501; acf_did=07f83a57d1d2e22942e0883200001501; Hm_lvt_e99aee90ec1b2106afe7ec3b199020a7=1556514266,1557050422,1557208315; acf_auth=; acf_auth_wl=; acf_uid=; acf_nickname=; acf_username=; acf_own_room=; acf_groupid=; acf_notification=; acf_phonestatus=; _dys_lastPageCode=page_video,page_video; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=1557209469; _dys_refer_action_code=click_author_video_cate2'try:req_content = requests.get(url,headers = headers)if req_content.status_code == 200:return req_contentprint('请求失败:',url)return Noneexcept:print('请求失败:', url)return None把时间换算成秒def str_to_int(time):try:time_array = time.split(':')time_int = (int(time_array[0])60)+int(time_array[1])return time_intexcept:print('~~~~~计算视频时间失败~~~~~')return None提取需要采集的数据def get_list(html,type = 1):data = []try:list_json = json.loads(str(html))for om in list_json['data']['list']:gtime = str_to_int(om['video_str_duration'])if gtime > config['TIME_START'] and gtime < config['TIME_ENT']:if type == 2:data.append({'title': om['title'], 'vid': om['url'].split('show/')[1]})else:data.append({'title': om['title'], 'vid': om['hash_id']})return dataexcept:print('~~~~~数据提取失败~~~~~')return None解析playlist.m3u8def get_ts_list(m3u8):data = []try:html_m3u8_json = json.loads(m3u8)m3u8_text = get_content_requests(html_m3u8_json['data']['video_url'])m3u8_vurl =html_m3u8_json['data']['video_url'].split('playlist.m3u8?')[0]if m3u8_text:get_text = re.findall(',\n(.?).ts(.?)\n',m3u8_text.text,re.S)for item in get_text:data.append(m3u8_vurl+item[0]+'.ts'+item[1])return datareturn Noneexcept:print('~~~~~解析playlist.m3u8失败~~~~~')return None 杀死moviepy产生的特定进程def killProcess(): 处理python程序在运行中出现的异常和错误try: pids方法查看系统全部进程pids = psutil.pids()for pid in pids: Process方法查看单个进程p = psutil.Process(pid) print('pid-%s,pname-%s' % (pid, p.name())) 进程名if p.name() == 'ffmpeg-win64-v4.1.exe': 关闭任务 /f是强制执行,/im对应程序名cmd = 'taskkill /f /im ffmpeg-win64-v4.1.exe 2>nul 1>null' python调用Shell脚本执行cmd命令os.system(cmd)except:pass下载.ts文件def download_ts(m3u8_list,name):try:if not os.path.exists(config['FILE_PATH']):os.makedirs(config['FILE_PATH'])if not os.path.exists(config['TS_PATH']):os.makedirs(config['TS_PATH'])if os.path.exists(config['FILE_PATH']+name+'.mp4'):name = name+'_'+str(int(time.time()))print('开始下载:',name)L = []R = []for p in m3u8_list:ts_find = get_content_requests(p)file_ts = '{0}{1}.ts'.format(config['TS_PATH'],md5(ts_find.content).hexdigest())with open(file_ts,'wb') as f:f.write(ts_find.content)R.append(file_ts)hebing = VideoFileClip(file_ts)L.append(hebing)killProcess()print('下载完成:',file_ts)mp4file = '{0}{1}.mp4'.format(config['FILE_PATH'],name)final_clip = concatenate_videoclips(L)final_clip.to_videofile(mp4file, fps=24, remove_temp=True)killProcess()loop_del_file(R)print('\n下载完成:',name)print('')return Trueexcept:print('~~~~~合成.ts文件失败~~~~~')return None下载视频列表def list_get_kong(list_json):for item in list_json:y = Trueif config['CHECKID']:if check_to_mongo(item['vid']):print('~~~~~检测到重复项~~~~~')y = Falseif y:get_show_html = get_content_requests('https://vmobile.douyu.com/video/getInfo?vid=' + item['vid'])if get_show_html:m3u8_list = get_ts_list(get_show_html.text)if m3u8_list:download = download_ts(m3u8_list, item['title'])if download: save_to_mango(item['vid'])time.sleep(config['TIME_GE'])控制器def main(page):if config['TYPE']==1:print('~~~~~按用户ID采集~~~~~')listurl = 'https://v.douyu.com/video/author/getAuthorVideoListByNew?up_id={0}&cate2_id=0&limit=30&page={1}'.format(config['UID'],page)get_list_html = get_content_requests(listurl)if get_list_html:list_json = get_list(get_list_html.text,1)if list_json:list_get_kong(list_json)else:print('~~~~~按列表ID采集~~~~~')listurl = 'https://v.douyu.com/video/video/listData?page={1}&cate2Id={0}&action=new'.format(config['CID'],page)get_list_html = get_content_requests(listurl)if get_list_html:list_json = get_list(get_list_html.text,2)if list_json:list_get_kong(list_json)初始化if __name__=='__main__':if config['POOL']:groups = [x for x in range(config['PAGE_START'],config['PAGE_END']+1)]pool = Pool()pool.map(main, groups)else:for item in range(config['PAGE_START'],config['PAGE_END']+1):main(item)print('~~~~~已经完成【所有操作】~~~~~') 总结:众所周知,BiliBili是一个学习的网站! 本篇文章为转载内容。原文链接:https://blog.csdn.net/qq_35875470/article/details/89857445。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-12-18 11:34:00
119
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 Proxy 、Relect、响应式 Proxy 、Relect、响应式 1. 监听对象的操作 2. Proxy基本使用 2.1 Proxy 的 set 和 get 捕获器 2.2 Proxy 所有捕获器 (13个) 2.3 Proxy 的 construct 和 apply 3. Reflect 3.1 Reflect 的作用 3.2 Reflect 的常见方法 3.3 Reflect 的使用 3.4 Receiver的作用 3.5 Reflect 的 construct 4. 响应式 4.1 什么是响应式? 4.2 响应式函数设计 4.3 响应式依赖的收集 4.4 监听对象的变化 4.5 对象的依赖管理 4.6 对 Depend 重构 4.7 创建响应式对象 4.8 Vue2 响应式原理 Proxy 、Relect、响应式 1. 监听对象的操作 需求:有一个对象,我们希望监听这个对象中的属性被设置或获取的过程 可以通过属性描述符中的存储属性描述符来做到 这段代码就利用了 Object.defineProperty 的存储属性描述符来对属性的操作进行监听 const obj = {name: 'why',age: 18}Object.keys(obj).forEach((key) => {let value = obj[key]Object.defineProperty(obj, key, {get: function () {console.log(监听到obj对象的${key}属性被访问了)return value},set: function (newValue) {console.log(监听到obj对象的${key}属性被设置值)value = newValue} })})obj.name = 'kobe'obj.age = 30console.log(obj.name)console.log(obj.age)/ 监听到obj对象的name属性被设置值监听到obj对象的age属性被设置值监听到obj对象的name属性被访问了kobe监听到obj对象的age属性被访问了30/ 属性描述符监听对象的缺点: 首先,Object.defineProperty 设计的初衷,不是为了去监听截止一个对象中所有的属性的 我们在定义某些属性的时候,初衷其实是定义普通的属性,但是后面我们强行将它变成了数据属性描述符 其次,如果我们想监听更加丰富的操作,比如新增属性、删除属性,那么 Object.defineProperty 是无能为力的 所以我们要知道,存储数据描述符设计的初衷并不是为了去监听一个完整的对象 Ps: 原来的对象是 数据属性描述符,通过 Object.defineProperty 变成了 访问属性描述符 2. Proxy基本使用 在ES6中,新增了一个Proxy类,这个类从名字就可以看出来,是用于帮助我们创建一个代理的: 也就是说,如果我们希望监听一个对象的相关操作,那么我们可以先创建一个代理对象(Proxy对象) 之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听我们想要对原对象进行哪些操作 将上面的案例用 Proxy 来实现一次: 首先,我们需要 new Proxy 对象,并且传入需要侦听的对象以及一个处理对象,可以称之为 handler; const p = new Proxy(target, handler) 其次,我们之后的操作都是直接对 Proxy 的操作,而不是原有的对象,因为我们需要在 handler 里面进行侦听 const obj = {name: 'why',age: 18}const objProxy = new Proxy(obj, {// 获取值时的捕获器get: function (target, key) {console.log(监听到obj对象的${key}属性被访问了)return target[key]},// 设置值时的捕获器set: function (target, key, newValue) {console.log(监听到obj对象的${key}属性被设置值)target[key] = newValue} })console.log(objProxy.name)console.log(objProxy.age)objProxy.name = 'kobe'objProxy.age = 30console.log(obj.name)console.log(obj.age)/ 监听到obj对象的name属性被访问了why监听到obj对象的age属性被访问了18监听到obj对象的name属性被设置值监听到obj对象的age属性被设置值kobe30/ 2.1 Proxy 的 set 和 get 捕获器 如果我们想要侦听某些具体的操作,那么就可以在 handler 中添加对应的捕捉器(Trap) set 和 get 分别对应的是函数类型 set 函数有四个参数: target:目标对象(侦听的对象) property:将被设置的属性 key value:新属性值 receiver:调用的代理对象 get 函数有三个参数 target:目标对象(侦听的对象) property:被获取的属性 key receiver:调用的代理对象 2.2 Proxy 所有捕获器 (13个) handler.getPrototypeOf() Object.getPrototypeOf 方法的捕捉器 handler.setPrototypeOf() Object.setPrototypeOf 方法的捕捉器 handler.isExtensible() Object.isExtensible 方法的捕捉器 handler.preventExtensions() Object.preventExtensions 方法的捕捉器 handler.getOwnPropertyDescriptor() Object.getOwnPropertyDescriptor 方法的捕捉器 handler.defineProperty() Object.defineProperty 方法的捕捉器 handler.ownKeys() Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器 handler.has() in 操作符的捕捉器 handler.get() 属性读取操作的捕捉器 handler.set() 属性设置操作的捕捉器 handler.deleteProperty() delete 操作符的捕捉器 handler.apply() 函数调用操作的捕捉器 handler.construct() new 操作符的捕捉器 const obj = {name: 'why',age: 18}const objProxy = new Proxy(obj, {// 获取值时的捕获器get: function (target, key) {console.log(监听到obj对象的${key}属性被访问了)return target[key]},// 设置值时的捕获器set: function (target, key, newValue) {console.log(监听到obj对象的${key}属性被设置值)target[key] = newValue},// 监听 in 的捕获器has: function (target, key) {console.log(监听到obj对象的${key}属性的in操作)return key in target},// 监听 delete 的捕获器deleteProperty: function (target, key) {console.log(监听到obj对象的${key}属性的delete操作)delete target[key]} })// in 操作符console.log('name' in objProxy)// delete 操作delete objProxy.name/ 监听到obj对象的name属性的in操作true监听到obj对象的name属性的delete操作/ 2.3 Proxy 的 construct 和 apply 到捕捉器中还有 construct 和 apply,它们是应用于函数对象的 function foo() {console.log('调用了 foo')}const fooProxy = new Proxy(foo, {apply: function (target, thisArg, argArray) {console.log(对 foo 函数进行了 apply 调用)target.apply(thisArg, argArray)},construct: function (target, argArray, newTarget) {console.log(对 foo 函数进行了 new 调用)return new target(...argArray)} })fooProxy.apply({}, ['abc', 'cba'])new fooProxy('abc', 'cba')/ 对 foo 函数进行了 apply 调用调用了 foo对 foo 函数进行了 new 调用调用了 foo/ 3. Reflect 3.1 Reflect 的作用 Reflect 也是 ES6 新增的一个 API,它是一个对象,字面的意思是反射 Reflect 的作用: 它主要提供了很多操作 JavaScript 对象的方法,有点像 Object 中操作对象的方法 比如 Reflect.getPrototypeOf(target) 类似于 Object.getPrototypeOf() 比如 Reflect.defineProperty(target, propertyKey, attributes) 类似于 Object.defineProperty() 如果我们有 Object 可以做这些操作,那么为什么还需要有Reflect这样的新增对象呢? 这是因为在早期的 ECMA 规范中没有考虑到这种对 对象本身 的操作如何设计会更加规范,所以将这些 API 放到了 Object上面 但是 Object 作为一个构造函数,这些操作实际上放到它身上并不合适 另外还包含一些类似于 in、delete 操作符,让 JS 看起来是会有一些奇怪的 所以在 ES6 中新增了 Reflect,让我们这些操作都集中到了 Reflect 对象上 那么 Object 和 Reflect 对象之间的 API 关系,可以参考 MDN 文档: 比较 Reflect 和 Object 方法 3.2 Reflect 的常见方法 Reflect中有哪些常见的方法呢?它和Proxy是一一对应的,也是13个 Reflect.getPrototypeOf(target) 类似于 Object.getPrototypeOf() Reflect.setPrototypeOf(target, prototype) 设置对象原型的函数. 返回一个 Boolean, 如果更新成功,则返回 true Reflect.isExtensible(target) 类似于 Object.isExtensible() Reflect.preventExtensions(target) 类似于 Object.preventExtensions() , 返回一个 Boolean Reflect.getOwnPropertyDescriptor(target, propertyKey) 类似于 Object.getOwnPropertyDescriptor() , 如果对象中存在该属性,则返回对应的属性描述符, 否则返回 undefined Reflect.defineProperty(target, propertyKey, attributes) 和 Object.defineProperty() 类似, 如果设置成功就会返回 true Reflect.ownKeys(target) 返回一个包含所有自身属性(不包含继承属性)的数组 (类似于 Object.keys(), 但不会受 enumerable 影响) Reflect.has(target, propertyKey) 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同 Reflect.get(target, propertyKey[, receiver]) 获取对象身上某个属性的值,类似于 target[name] Reflect.set(target, propertyKey, value[, receiver]) 将值分配给属性的函数,返回一个 Boolean,如果更新成功,则返回 true Reflect.deleteProperty(target, propertyKey) 作为函数的 delete 操作符,相当于执行 delete target[name] Reflect.apply(target, thisArgument, argumentsList) 对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似 Reflect.construct(target, argumentsList[, newTarget]) 对构造函数进行 new 操作,相当于执行 new target(...args) 3.3 Reflect 的使用 那么我们可以将之前Proxy案例中对原对象的操作,都修改为Reflect来操作 const obj = {name: 'why',age: 18}const objProxy = new Proxy(obj, {get: function (target, key) {console.log(监听到obj对象的${key}属性被访问了)return Reflect.get(target, key)// return target[key] // 对原来对象进行了直接操作},set: function (target, key, newValue) {console.log(监听到obj对象的${key}属性被设置值)Reflect.set(target, key, newValue)// target[key] = newValue // 对原来对象进行了直接操作} })objProxy.name = 'kobe'console.log(objProxy.name)/ 监听到obj对象的name属性被设置值监听到obj对象的name属性被访问了kobe/ 3.4 Receiver的作用 我们发现在使用getter、setter的时候有一个receiver的参数,它的作用是什么呢? 如果我们的源对象(obj)有 setter 、getter 的访问器属性,那么可以通过 receiver 来改变里面的 this const obj = {_name: 'why',get name() {return this._name // 不使用receiver, _name属性的操作不会被objProxy代理,因为this指向obj},set name(newValue) {this._name = newValue} }const objProxy = new Proxy(obj, {get: function (target, key, receiver) {// receiver 是创建出来的代理对象console.log('get 方法被访问-------', key, receiver)console.log(objProxy === receiver) // truereturn Reflect.get(target, key, receiver)},set: function (target, key, newValue, receiver) {Reflect.set(target, key, newValue, receiver)} })objProxy.name = 'kobe'console.log(objProxy.name) // kobe/ get 方法被访问------- name { _name: 'kobe', name: [Getter/Setter] }trueget 方法被访问------- _name { _name: 'kobe', name: [Getter/Setter] }truekobe/ 3.5 Reflect 的 construct function Student(name, age) {this.name = namethis.age = age}function Teacher() {}const stu = new Student('why', 18)console.log(stu)console.log(stu.__proto__ === Student.prototype)/ Student { name: 'why', age: 18 }true/// 执行 Student 函数中的内容,但是创建出来的对象是 Teacher 对象const teacher = Reflect.construct(Student, ['why', 18], Teacher)console.log(teacher)console.log(teacher.__proto__ === Teacher.prototype)/ Teacher { name: 'why', age: 18 }true/ 4. 响应式 4.1 什么是响应式? 先来看一下响应式意味着什么?我们来看一段代码: m 有一个初始化的值,有一段代码使用了这个值; 那么在 m 有一个新的值时,这段代码可以自动重新执行 let m = 0// 一段代码console.log(m)console.log(m 2)console.log(m 2)m = 200 上面的这样一种可以自动响应数据变量的代码机制,我们就称之为是响应式的 对象的响应式 4.2 响应式函数设计 首先,执行的代码中可能不止一行代码,所以我们可以将这些代码放到一个函数中: 那么问题就变成了,当数据发生变化时,自动去执行某一个函数; 但是有一个问题:在开发中是有很多的函数的,如何区分一个函数需要响应式,还是不需要响应式呢? 很明显,下面的函数中 foo 需要在 obj 的 name 发生变化时,重新执行,做出相应; bar 函数是一个完全独立于 obj 的函数,它不需要执行任何响应式的操作; // 对象的响应式const obj = {name: 'why',age: 18}function foo() {const newName = obj.nameconsole.log('你好啊,李银河')console.log('Hello World')console.log(obj.name)}function bar() {console.log('普通的其他函数')console.log('这个函数不需要有任何的响应式')}obj.name = 'kobe' // name 发生改变时候 foo 函数执行 响应式函数的实现 watchFn 如何区分响应式函数? 这个时候我们封装一个新的函数 watchFn 凡是传入到 watchFn 的函数,就是需要响应式的 其他默认定义的函数都是不需要响应式的 / 封装一个响应式的函数 /let reactiveFns = []function watchFn(fn) {reactiveFns.push(fn)}// 对象的响应式const obj = {name: 'why',age: 18}watchFn(function foo() {const newName = obj.nameconsole.log('你好啊,李银河')console.log('Hello World')console.log(obj.name)})watchFn(function demo() {console.log(obj.name, 'demo function ---------')})function bar() {console.log('普通的其他函数')console.log('这个函数不需要有任何的响应式')}obj.name = 'kobe' // name 发生改变时候 foo 函数执行reactiveFns.forEach((fn) => {fn()}) 4.3 响应式依赖的收集 目前收集的依赖是放到一个数组中来保存的,但是这里会存在数据管理的问题: 在实际开发中需要监听很多对象的响应式 这些对象需要监听的不只是一个属性,它们很多属性的变化,都会有对应的响应式函数 不可能在全局维护一大堆的数组来保存这些响应函数 所以要设计一个类,这个类用于管理某一个对象的某一个属性的所有响应式函数: 相当于替代了原来的简单 reactiveFns 的数组; class Depend {constructor() {this.reactiveFns = []}addDepend(reactiveFn) {this.reactiveFns.push(reactiveFn)}notify() {this.reactiveFns.forEach((fn) => {fn()})} }const depend = new Depend()function watchFn(fn) {depend.addDepend(fn)}// 对象的响应式const obj = {name: 'why', // depend 对象age: 18 // depend 对象}watchFn(function foo() {const newName = obj.nameconsole.log('你好啊,李银河')console.log('Hello World')console.log(obj.name)})watchFn(function demo() {console.log(obj.name, 'demo function ---------')})function bar() {console.log('普通的其他函数')console.log('这个函数不需要有任何的响应式')}obj.name = 'kobe'depend.notify() 4.4 监听对象的变化 那么接下来就可以通过之前的方式来监听对象的变化: 方式一:通过 Object.defineProperty 的方式(vue2采用的方式); 方式二:通过 new Proxy 的方式(vue3采用的方式); 我们这里先以Proxy的方式来监听 class Depend {constructor() {this.reactiveFns = []}addDepend(reactiveFn) {this.reactiveFns.push(reactiveFn)}notify() {this.reactiveFns.forEach((fn) => {fn()})} }const depend = new Depend()function watchFn(fn) {depend.addDepend(fn)}// 对象的响应式const obj = {name: 'why', // depend 对象age: 18 // depend 对象}// 监听对象的属性变化:Proxy(vue3)/Object.defineProperty(vue2)const objProxy = new Proxy(obj, {get: function (target, key, receiver) {return Reflect.get(target, key, receiver)},set: function (target, key, newValue, receiver) {Reflect.set(target, key, newValue, receiver)depend.notify()} })watchFn(function foo() {const newName = objProxy.nameconsole.log('你好啊,李银河')console.log('Hello World')console.log(objProxy.name)})watchFn(function demo() {console.log(objProxy.name, 'demo function ---------')})objProxy.name = 'kobe'objProxy.name = 'james'/ 你好啊,李银河Hello Worldkobekobe demo function ---------你好啊,李银河Hello Worldjamesjames demo function ---------/ 4.5 对象的依赖管理 目前是创建了一个 Depend 对象,用来管理对于 name 变化需要监听的响应函数: 但是实际开发中我们会有不同的对象,另外会有不同的属性需要管理; 如何可以使用一种数据结构来管理不同对象的不同依赖关系呢? 在前面我们刚刚学习过 WeakMap,并且在学习 WeakMap 的时候我讲到了后面通过 WeakMap 如何管理这种响应式的数据依赖: 实现 可以写一个 getDepend 函数专门来管理这种依赖关系 / 封装一个获取depend的函数 /const taregtMap = new WeakMap()function getDepend(target, key) {// 根据target对象获取mapconst map = taregtMap.get(target)if (!map) {map = new Map()taregtMap.set(target, map)}// 根据key获取depend对象const depend = map.get(key)if (!depend) {depend = new Depend()map.set(key, depend)}return depend}// 监听对象的属性变化:Proxy(vue3)/Object.defineProperty(vue2)const objProxy = new Proxy(obj, {get: function (target, key, receiver) {return Reflect.get(target, key, receiver)},set: function (target, key, newValue, receiver) {Reflect.set(target, key, newValue, receiver)const depend = getDepend(target, key)depend.notify()} }) 正确的依赖收集 我们之前收集依赖的地方是在 watchFn 中: 但是这种收集依赖的方式我们根本不知道是哪一个 key 的哪一个 depend 需要收集依赖; 只能针对一个单独的 depend 对象来添加你的依赖对象; 那么正确的应该是在哪里收集呢?应该在我们调用了 Proxy 的 get 捕获器时 因为如果一个函数中使用了某个对象的 key,那么它应该被收集依赖 / 封装一个响应式函数 /let activeReactviceFn = nullfunction watchFn(fn) {activeReactviceFn = fnfn()activeReactviceFn = null}/ 封装一个获取depend的函数 /const taregtMap = new WeakMap()function getDepend(target, key) {// 根据target对象获取maplet map = taregtMap.get(target)if (!map) {map = new Map()taregtMap.set(target, map)}// 根据key获取depend对象let depend = map.get(key)if (!depend) {depend = new Depend()map.set(key, depend)}return depend}// 监听对象的属性变化:Proxy(vue3)/Object.defineProperty(vue2)const objProxy = new Proxy(obj, {get: function (target, key, receiver) {// 根据 target key 获取对应的 depnedconst depend = getDepend(target, key)// 给 depend 对象中添加响应式函数activeReactviceFn && depend.addDepend(activeReactviceFn)return Reflect.get(target, key, receiver)},set: function (target, key, newValue, receiver) {Reflect.set(target, key, newValue, receiver)const depend = getDepend(target, key)depend.notify()} }) 4.6 对 Depend 重构 两个问题: 问题一:如果函数中有用到两次 key,比如 name,那么这个函数会被收集两次 问题二:我们并不希望将添加 reactiveFn 放到 get 中,因为它是属于 Depend 的行为 所以我们需要对 Depend 类进行重构: 解决问题一的方法:不使用数组,而是使用 Set 解决问题二的方法:添加一个新的方法,用于收集依赖 // 保存当前需要收集的响应式函数let activeReactviceFn = nullclass Depend {constructor() {this.reactiveFns = new Set()}depend() {if (activeReactviceFn) {this.reactiveFns.add(activeReactviceFn)} }addDepend(reactiveFn) {this.reactiveFns.add(reactiveFn)}notify() {this.reactiveFns.forEach((fn) => {fn()})} }// 对象的响应式const obj = {name: 'why', // depend 对象age: 18 // depend 对象}/ 封装一个响应式函数 /function watchFn(fn) {activeReactviceFn = fnfn()activeReactviceFn = null}/ 封装一个获取depend的函数 /const taregtMap = new WeakMap()function getDepend(target, key) {// 根据target对象获取maplet map = taregtMap.get(target)if (!map) {map = new Map()taregtMap.set(target, map)}// 根据key获取depend对象let depend = map.get(key)if (!depend) {depend = new Depend()map.set(key, depend)}return depend}// 监听对象的属性变化:Proxy(vue3)/Object.defineProperty(vue2)const objProxy = new Proxy(obj, {get: function (target, key, receiver) {// 根据 target key 获取对应的 depnedconst depend = getDepend(target, key)// 给 depend 对象中添加响应式函数depend.depend()return Reflect.get(target, key, receiver)},set: function (target, key, newValue, receiver) {Reflect.set(target, key, newValue, receiver)const depend = getDepend(target, key)depend.notify()} })watchFn(function () {console.log(objProxy.name, '--------------')console.log(objProxy.name, '++++++++++++++')})objProxy.name = 'kobe'/ why --------------why ++++++++++++++kobe --------------kobe ++++++++++++++/ 4.7 创建响应式对象 目前的响应式是针对于obj一个对象的,我们可以创建出来一个函数,针对所有的对象都可以变成响应式对象 / 保存当前需要收集的响应式函数 /let activeReactviceFn = null/ 依赖收集类 /class Depend {constructor() {this.reactiveFns = new Set()}depend() {if (activeReactviceFn) {this.reactiveFns.add(activeReactviceFn)} }addDepend(reactiveFn) {this.reactiveFns.add(reactiveFn)}notify() {this.reactiveFns.forEach((fn) => {fn()})} }/ 封装一个响应式函数 /function watchFn(fn) {activeReactviceFn = fnfn()activeReactviceFn = null}/ 封装一个获取depend的函数 /const taregtMap = new WeakMap()function getDepend(target, key) {// 根据target对象获取maplet map = taregtMap.get(target)if (!map) {map = new Map()taregtMap.set(target, map)}// 根据key获取depend对象let depend = map.get(key)if (!depend) {depend = new Depend()map.set(key, depend)}return depend}/ 创建响应式对象函数 /function reactive(obj) {// 监听对象的属性变化:Proxy(vue3)/Object.defineProperty(vue2)return new Proxy(obj, {get: function (target, key, receiver) {// 根据 target key 获取对应的 depnedconst depend = getDepend(target, key)// 给 depend 对象中添加响应式函数depend.depend()return Reflect.get(target, key, receiver)},set: function (target, key, newValue, receiver) {Reflect.set(target, key, newValue, receiver)const depend = getDepend(target, key)depend.notify()} })}const info = reactive({address: '广州市',height: 1.88})watchFn(() => {console.log(info.address, '---')})info.address = '北京市' 4.8 Vue2 响应式原理 前面所实现的响应式的代码,其实就是 Vue3 中的响应式原理: Vue3 主要是通过 Proxy 来监听数据的变化以及收集相关的依赖的 Vue2 中通过 Object.defineProerty的方式来实现对象属性的监听 可以将 reactive 函数进行如下的重构: 在传入对象时,我们可以遍历所有的 key,并且通过属性存储描述符来监听属性的获取和修改 在 setter 和 getter 方法中的逻辑和前面的 Proxy 是一致的 / 保存当前需要收集的响应式函数 /let activeReactviceFn = null/ 依赖收集类 /class Depend {constructor() {this.reactiveFns = new Set()}depend() {if (activeReactviceFn) {this.reactiveFns.add(activeReactviceFn)} }addDepend(reactiveFn) {this.reactiveFns.add(reactiveFn)}notify() {this.reactiveFns.forEach((fn) => {fn()})} }/ 封装一个响应式函数 /function watchFn(fn) {activeReactviceFn = fnfn()activeReactviceFn = null}/ 封装一个获取depend的函数 /const taregtMap = new WeakMap()function getDepend(target, key) {// 根据target对象获取maplet map = taregtMap.get(target)if (!map) {map = new Map()taregtMap.set(target, map)}// 根据key获取depend对象let depend = map.get(key)if (!depend) {depend = new Depend()map.set(key, depend)}return depend}/ 创建响应式对象函数 /function reactive(obj) {Object.keys(obj).forEach((key) => {let value = obj[key]Object.defineProperty(obj, key, {get: function () {const dep = getDepend(obj, key)dep.depend()return value},set: function (newValue) {value = newValueconst dep = getDepend(obj, key)dep.notify()} })})return obj}const info = reactive({address: '广州市',height: 1.88})watchFn(() => {console.log(info.address, '---')})info.address = '北京市' 本篇文章为转载内容。原文链接:https://blog.csdn.net/wanghuan1020/article/details/126774033。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-01-11 12:37:47
679
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 目录 一、建模背景及目的及数据源说明 二、描述性分析 2.1 连续自变量与连续因变量的相关性分析 2.2 二分类变量与连续变量的相关性分析 2.3 多分类变量与连续变量的相关性分析 三、模型建立与诊断 3.1 一元线形回归及模型解读 3.2 残差可视化分析 3.3 多元线性回归 一、建模背景及目的及数据源说明 本案例数据来源于常国珍等人的《Python数据科学》一书第7章中的信用卡公司客户申请信息(年龄、收入、地区等信息)以及已有开卡客户的申请信息和信用卡消费信息数据,案例希望通过对该数据的分析和建模,根据已有的开卡用户的用户信息和消费来线形回归模型,来预测未开卡用户的消费潜力。数据下载见如下链https://download.csdn.net/download/baidu_26137595/85101874 数据读入及示例: raw = pd.read_csv('./data/creditcard_exp.csv', skipinitialspace = True)raw.head() 数据字段及说明: Acc: 是否开卡, 为0说明未开卡,对应的 avg_exp 为NaN;为1说明已开卡,对应avg_exp有值 avg_exp: 月均信用卡支出 avg_exp_ln:月均信用卡支出的对熟 gender : 性别 Ownrent: 是否自有住房 Selfempl: 是否自谋职业 Income:收入 dist_home_val: 所住小区均价 w dist_avg_income: 当地人均收入 age2: 年龄的平方 high_avg: 高出当地平均收入 edu_class:教育等级,0、1、2、3 依次是小学、初中、高中、大学 二、描述性分析 首先可筛选Acc为1的数据,分别以avg_exp为因变量,其余变量为自变量进行数据探索,主要是发现自变量和因变量是否有线形关系。 raw_1 = raw[raw['Acc'] == 1] 2.1 连续自变量与连续因变量的相关性分析 首先对连续变量和目标变量进行相关性分析,因变量avg_exp为连续变量,一般可以用相关系数来看其线形相关性。 cons_vasr = ['avg_exp', 'avg_exp_ln', 'Age', 'Income', 'dist_home_val', 'dist_avg_income', 'age2', 'high_avg']raw_1[cons_vasr].corr()vg']].corr() 结果如下,可以看到收入 Income 和当地人均收入 dist_avg_income这两个变量和avg_exp月均信用卡支出有较强的相关性,同时观察自变量间的相关性可发现人均收入 Income 和当地人均收入 dist_avg_income 之间也有较强的相关性,相关系数为0.99,说明接下来我们可以把这两个变量加入模型,但要注意可能会存在多重共线性。 2.2 二分类变量与连续变量的相关性分析 分类变量和连续变量之间的相关性可以用t检验进行,接下来以是否自有住房 Ownrent 变量 和 月均收入之间进行相关性检验。首先查看Ownrent 不同取值的数量以及avg_exp均值分布情况如何: pd.pivot_table(raw_1, values = ['avg_exp'], index = ['Ownrent'], aggfunc = {'avg_exp': ['count', np.mean]}) 接着分别对 Ownrent 为0、1的 avg_exp 进行t检验: import scipy.stats as st 引入scipy.stats进行t检验 创建变量Ownrent_0 = raw_1[raw_1['Ownrent'] == 0]['avg_exp'].valuesOwnrent_1 = raw_1[raw_1['Ownrent'] == 1]['avg_exp'].valuesst.ttest_ind(Ownrent_0, Ownrent_1, equal_var = True) p值为0.01 < 0.05,可以拒绝原假设,即认为是否自有住房和月均信用卡支出是相关的。 2.3 多分类变量与连续变量的相关性分析 多分类变量和连续变量之间的相关性检验可以用多次t检验进行,但较为繁琐,用方差分析进行快速检验相关性,然后再运用多重检验查看具体是哪些处理之间存在差异。以教育水平edu_class为例进行分析,同理首先查看分布 raw_1.pivot_table(index = 'edu_class', values = ['avg_exp'], aggfunc={'avg_exp': ['count', np.mean]}) 可以看到不同教育水平之间消费水平有明显差异,接下来通过方差分析进行检验差异是否明显。 from statsmodels.stats.anova import anova_lm 引入anova_lm进行方差分析from ststsmodels.stats.formula import ols 引入ols进行线性回归建模lm = ols('avg_exp~C(edu_class)', data = raw_1).fit() C(edu_class) 将数值型的变量指定为分类型anova_lm(lm, typ = 2) 可以看到不同教育水平之间的月均消费支出之间的差异是显著的,继续用多重检验来看哪些处理之间是显著的。 from statsmodels.stats.multicomp import MultiComparison 引入MultiComparison进行tukey多重检验mc = MultiComparison(raw_1['avg_exp'],raw_1['edu_class'])tukey_result = mc.tukeyhsd(alpha = 0.5)print(tukey_result) 结果是每个处理之间因变量差异的显著性,最后一列reject都为True说明各组之间均存在显著差异。 三、模型建立与诊断 3.1 一元线性回归及模型解读 以Income为自变量,以avg_exp为因变量建立一元线形回归并对模型结果进行解释 lm_1 = ols('avg_exp ~ Income', data = raw_1).fit()print(lm_1.summary()) 首先从第一部分可以看到R^2为0.454,整个模型的F检验p值小于0.05,说明模型通过显著性检验。 其次模型结果的第二块也表明自变量和截距也通过显著性检验。 最后一部分主要是对残差进行检验,左侧Omnibus、Prob(Omnibus)主要是对偏度Skew和峰度Kurtosis进行检验,正态分布的偏度为0,峰度为3,模型的Prob(Omnibus)值为0.156大于0.05,说明不能拒绝残差符合正态分布。 右侧Durbin-Watson主要是对残差的自相关性进行检(改检验可表示为,为残差之间的相关系数),Durbin-Watson的取值范围是0-4,越接近2说明残差不存在自相关性,越接近0说明存在正相关,越接近4说明存在负相关性。 右侧Jarque-Bera (JB)、Prob(JB)是对残差正态性检验,可以用来判断残差是否符合正态分布,本案例中Prob(JB)值为0.173 > 0.05,基不能拒绝残差服从正态分布。 右侧Cond. No.是多重共线性检验,该值越大,共线性越严重。 整体上看模型虽然拟合效果没那么好,但是显著性通过了检验。接下来看一下模型具体的系数,Income的系数为97.7说明模型收入越高信用卡消费越高,是符合业务预期的。 3.2 残差可视化分析 接下来对残差进一步进行可视化分析,主要看残差是否满足以下几个假定,并尝试通过对自变量、因变量进行调整来优化模型。首先来回顾一下残差需要满足的几个假定: a.残差的要服从均值为0,方差为的正态分布; b.残差之间要相互独立 c.残差和自变量没有相关性 (1)通过残差图进行模型优化 模型avg_exp ~ Income的自变量与残差分布图、残差qq图、模型拟合情况图即自变量与因变量及其预测值的图像 lm_1 = ols('avg_exp ~ Income', data = raw_1).fit() 建模raw_1['resid_1'] = lm_1.resid 模型残差raw_1['resid_1_rank'] = raw_1['resid_1'].rank(ascending = False, pct = True) 计算残差的百分位数raw_1['pred_1'] = lm_1.predict() 添加预测值plt.figure(figsize = (20, 6)) 自变量与残差分布图ax1 = plt.subplot(131)ax1.scatter('Income', 'resid', data = raw_1)ax1.set_title('Income & resid') 残差的qq图ax2 = plt.subplot(132)stats.probplot(raw_1['resid_1_rank'], dist = 'norm', plot = ax2) 模型拟合情况图,自变量与因变量以及模型预测值ax3 = plt.subplot(133)ax3.scatter('Income', 'avg_exp', data = raw_1)ax3.plot('Income', 'pred_1', data = raw_1, color = 'red')ax3.legend()ax3.text(12, 1920, 'pred func R^2: %.2f'% lm_1.rsquared)ax3.set_title('Income & avg_exp') 从第一个自变量和残差散点图可以看出,残差基本符合对称分布,但随着自变量增大,残差也在变大,存在方差不齐的情况。第二个图残差的qq图可以看出,残差近似正态分布。第三个图可以看模型的拟合效果并不是很好,R^2只有0.45。对avg_exp取对数,能够改善预测值越大残差越大的情况,但由于只对因变量取对数导致模型不好解释,对自变量Income同时取对数,代码和以上类似,只是改变因变量和自变量形式而已,以下是残差图,可以看到残差的异方差现象被有效的抑制,并且R^2也得到了提高。 (2)通过残差图发现强影响点 仔细观察以上图像结果,左下侧有两个较为异常的数据,对模型的拟和效果有较大的影响, 对于这种影响较大的可将其进行删除并重新建模: 计算学生化残差raw_1['resid_t'] = (raw_1['resid_2'] - raw_1['resid_2'].mean())/raw_1['resid_2'].std() raw_1[abs(raw_1['resid_t']) > 2] 将残差大于2的筛选出来 将强影响点删除后,得到的结果如下,模型结果更稳定。 3.3 多元线性回归 上一篇文章有说到多重共线性会对模型产生致命的影响,用方差膨胀因子来处理的话会非常繁琐。通过正则化处理如Lasso回归,能够产生某些严格等于0的系数,从而达到变量筛选的目的。接下来以Lasso为例,首先用LassoCV来找到最优的alpha。由于statsmodels中的ols的fit_regularized方法没有很好的实现,所以用sklearn中linear_model模块来进行建模 from sklearn.preprocessing import StandardScaler sklearn进行线性回归前必须要进行标准化from sklearn.linear_model import LassoCV Lasso的交叉验证方法con_xcols = ['Age', 'Income', 'dist_home_val', 'dist_avg_income']scaler = StandardScaler()X = scaler.fit_transform(raw_1[con_xcols])y = raw_1['avg_exp_ln']lasso_alphas = np.logspace(-3, 0, 100, base = 10)lcv = LassoCV(alphas = lasso_alphas, cv = 10)lcv.fit(X, y)print('best alpha %.4f' % lcv.alpha_)print('the r-square %.4f' % lcv.score(X, y)) 接下来画出不同alpha下的岭迹图,来看alpha值对系数的影响 from sklearn.linear_model import Lassocoefs = []lasso = Lasso()for i in lasso_alphas:lasso.set_params(alpha = i)lasso.fit(X, y)coefs.append(lasso.coef_)ax = plt.gca()ax.plot(lasso_alphas, coefs)ax.set_xscale('log')ax.set_xlabel('$\\alpha$')ax.set_ylabel('coefs value') 从图中可以看到随着alpha的增大,系数不断在减小,有些系数会优先收缩为0,再继续增大时所欲系数都会为0,通过该特性从而达到变量筛选的目的。将LassoCV得到的系数打印出来,可以看到用户月均信用卡支出和当地小区均价、当地人均收入成正比,当地人均收入水平的影响更大。 以上就是线形回归在应用时的注意事项。 本篇文章为转载内容。原文链接:https://blog.csdn.net/baidu_26137595/article/details/123766191。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-11-23 15:52:56
106
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 在PC端点击图片,鼠标右键可把图片素材另存到桌面使用,手机端可长按图片保存到本地相册,夏欢和认为有用的话就点个赞,三连就更满足我的期待了 JPanel切换案例 package swing; public class mains { public static void main(String[] args) { new swingJpanelQieHuan(); } } package swing; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.; public class swingJpanelQieHuan extends JFrame{ public static JPanel jpRed,jpPink,jpBlueRightBottom1, jpGreenRightBottom2; public static JButton anNiu1,anNiu2; JLabel JLabel1; public static JLabel JLabel2; public swingJpanelQieHuan(){ this.setLayout(null); this.setSize(700,700); this.setLocationRelativeTo(null); jpRed=new JPanel(); jpPink=new JPanel(); jpBlueRightBottom1=new JPanel(); jpGreenRightBottom2=new JPanel(); jpRed.setLayout(null); anNiu1=new JButton("点赞界面"); anNiu2=new JButton("三连关注界面"); anNiu1.setBounds(150,30,120,30); anNiu2.setBounds(300,30,120,30); anNiu1.addActionListener(new swingJpanelShiJian(this)); anNiu2.addActionListener(new swingJpanelShiJian(this)); jpRed.add(anNiu1);jpRed.add(anNiu2); jpRed.setBorder(BorderFactory.createLineBorder(Color.red)); jpPink.setBorder(BorderFactory.createLineBorder(Color.pink)); jpBlueRightBottom1.setBorder (BorderFactory.createLineBorder(Color.blue)); jpGreenRightBottom2.setBorder (BorderFactory.createLineBorder(Color.green)); jpRed.setBounds(10,10,600,150); jpPink.setBounds(10,170,200,450); jpBlueRightBottom1.setBounds(220, 170, 380, 450); jpGreenRightBottom2.setBounds(220, 170, 380, 450); JLabel1 = new JLabel(); JLabel2=new JLabel(); JLabel1. setIcon(new ImageIcon("img//1.png")); JLabel2. setIcon(new ImageIcon("img//2.png")); jpBlueRightBottom1.add(JLabel1); jpGreenRightBottom2.add(JLabel2); this.add(jpRed);this.add(jpPink); this.add(jpGreenRightBottom2); this.add(jpBlueRightBottom1); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } class swingJpanelShiJian implements ActionListener{ //jieShou接收 //chuangTi窗体 public static swingJpanelQieHuan jieShou; public swingJpanelShiJian(swingJpanelQieHuan chuangTi){ jieShou=chuangTi; } @Override public void actionPerformed(ActionEvent arg0) { String neiRong=arg0.getActionCommand(); if(neiRong.equals("点赞界面")){ jieShou.jpBlueRightBottom1.setVisible(true); jieShou.jpGreenRightBottom2.setVisible(false); }else if(neiRong.equals("三连关注界面")){ jieShou.jpBlueRightBottom1.setVisible(false); jieShou.jpGreenRightBottom2.setVisible(true); } } } JTree树形控件点击内容弹出新的窗体 package swing; public class mains { public static void main(String[] args) { new swingJpanelQieHuan(); } } package swing; import java.awt.Color; import java.awt.Font; import javax.swing.; public class newDengLu extends JFrame{ public static JLabel lb1,lb2,lb3,lb4=null; public static JTextField txt1=null; public static JPasswordField pwd=null; public static JComboBox com=null; public static JButton btn1,btn2=null; public newDengLu(){ this.setTitle("诗书画唱登录页面"); this.setLayout(null); this.setSize(500,400); this.setLocationRelativeTo(null); lb1=new JLabel("用户名"); lb2=new JLabel("用户密码"); lb3=new JLabel("用户类型"); lb4=new JLabel("登录窗体"); Font f=new Font("微软雅黑",Font.BOLD,35); lb4.setFont(f); lb4.setForeground(Color.red); lb4.setBounds(160,30,140,40); lb1.setBounds(100, 100, 70,30); lb2.setBounds(100,140,70,30); lb3.setBounds(100,180,70,30); txt1=new JTextField(); txt1.setBounds(170,100,150,30); pwd=new JPasswordField(); pwd.setBounds(170,140,150,30); com=new JComboBox(); com.addItem("会员用户"); com.addItem("普通用户"); com.setBounds(170,180,150,30); btn1=new JButton("登录"); btn1.setBounds(130,220,70,30); btn2=new JButton("取消"); btn2.setBounds(240,220,70,30); this.add(lb1);this.add(lb2);this.add(lb3); this.add(txt1);this.add(pwd);this.add(com); this.add(btn1);this.add(btn2);this.add(lb4); //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } package swing; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; public class swingJpanelQieHuan extends JFrame{ public static JPanel jpRed,jpPinkLeft,jpBlueRightBottom1, jpGreenRightBottom2; public static JTree JTree1,JTree2; public static JButton anNiu1,anNiu2; public static JLabel JLabel1,JLabel2; public swingJpanelQieHuan(){ this.setLayout(null); this.setSize(700,700); this.setLocationRelativeTo(null); jpRed=new JPanel(); jpPinkLeft=new JPanel(); jpBlueRightBottom1=new JPanel(); jpGreenRightBottom2=new JPanel(); jpRed.setLayout(null); anNiu1=new JButton("点赞界面"); anNiu2=new JButton("三连关注界面"); anNiu1.setBounds(150,30,120,30); anNiu2.setBounds(300,30,120,30); anNiu1.addActionListener(new swingJpanelShiJian(this)); anNiu2.addActionListener(new swingJpanelShiJian(this)); jpRed.add(anNiu1);jpRed.add(anNiu2); jpRed.setBorder(BorderFactory.createLineBorder(Color.red)); jpPinkLeft.setBorder(BorderFactory.createLineBorder(Color.pink)); jpBlueRightBottom1.setBorder (BorderFactory.createLineBorder(Color.blue)); jpGreenRightBottom2.setBorder (BorderFactory.createLineBorder(Color.green)); jpRed.setBounds(10,10,600,150); jpPinkLeft.setBounds(10,170,200,450); jpBlueRightBottom1.setBounds(220, 170, 380, 450); jpGreenRightBottom2.setBounds(220, 170, 380, 450); JLabel1 = new JLabel(); JLabel2=new JLabel(); JLabel1. setIcon(new ImageIcon("img//1.png")); JLabel2. setIcon(new ImageIcon("img//2.png")); jpBlueRightBottom1.add(JLabel1); jpGreenRightBottom2.add(JLabel2); DefaultMutableTreeNode dmtn1 = new DefaultMutableTreeNode("图书管理"); DefaultMutableTreeNode dmtn_yonghu = new DefaultMutableTreeNode ("用户管理"); DefaultMutableTreeNode dmtnQieHuan = new DefaultMutableTreeNode ("切换到登录界面"); DefaultMutableTreeNode dmtn_yonghu_insert = new DefaultMutableTreeNode("增加用户"); DefaultMutableTreeNode dmtn_yonghu_update = new DefaultMutableTreeNode("修改用户"); DefaultMutableTreeNode dmtn_yonghu_delete = new DefaultMutableTreeNode("删除用户"); DefaultMutableTreeNode dmtn_yonghu_select = new DefaultMutableTreeNode("查询用户"); DefaultMutableTreeNode dmtn_jieyue = new DefaultMutableTreeNode("借阅管理"); DefaultMutableTreeNode dmtn_jieyue_insert = new DefaultMutableTreeNode("增加借阅信息"); DefaultMutableTreeNode dmtn_jieyue_update = new DefaultMutableTreeNode("修改借阅信息"); DefaultMutableTreeNode dmtn_jieyue_delete = new DefaultMutableTreeNode("删除借阅信息"); DefaultMutableTreeNode dmtn_jieyue_select = new DefaultMutableTreeNode("查询借阅信息"); dmtn_yonghu.add(dmtnQieHuan); dmtn_yonghu.add(dmtn_yonghu_insert); dmtn_yonghu.add(dmtn_yonghu_update); dmtn_yonghu.add(dmtn_yonghu_delete); dmtn_yonghu.add(dmtn_yonghu_select); dmtn_jieyue.add(dmtn_jieyue_insert); dmtn_jieyue.add(dmtn_jieyue_update); dmtn_jieyue.add(dmtn_jieyue_delete); dmtn_jieyue.add(dmtn_jieyue_select); dmtn1.add(dmtn_yonghu); dmtn1.add(dmtn_jieyue); JTree1 = new JTree(dmtn1); JTree1.addTreeSelectionListener(new swingJpanelShiJian(this)); JTree1.setBackground(Color.white); jpPinkLeft.setBackground(Color.white); //JTree1.setBounds(10,170,200,450);在这里是一句没效果的代码 jpPinkLeft.add(JTree1); this.add(jpRed);this.add(jpPinkLeft); this.add(jpGreenRightBottom2); this.add(jpBlueRightBottom1); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } class swingJpanelShiJian implements ActionListener, TreeSelectionListener{ //jieShou接收 //chuangTi窗体 public static swingJpanelQieHuan jieShou; public swingJpanelShiJian(swingJpanelQieHuan chuangTi){ jieShou=chuangTi; } @Override public void actionPerformed(ActionEvent arg0) { String neiRong=arg0.getActionCommand(); if(neiRong.equals("点赞界面")){ jieShou.jpBlueRightBottom1.setVisible(true); jieShou.jpGreenRightBottom2.setVisible(false); }else if(neiRong.equals("三连关注界面")){ jieShou.jpBlueRightBottom1.setVisible(false); jieShou.jpGreenRightBottom2.setVisible(true); } } @Override public void valueChanged(TreeSelectionEvent arg0) { DefaultMutableTreeNode str = (DefaultMutableTreeNode) jieShou.JTree1 .getLastSelectedPathComponent(); if (str.toString().equals("切换到登录界面")) { new newDengLu(); } else { } } } JTable初始化表格 package swing; public class mains { public static void main(String[] args) { new swingBiaoGe(); } } package swing; import java.util.Vector; import javax.swing.; import javax.swing.table.DefaultTableModel; public class swingBiaoGe extends JFrame{ //要声明 : 装载内容的容器,table的控件, 容器的标题, 容器的具体的内容。 public static JTable biaoGe=null;//JTable为表格的控件 //要声明装载内容的容器,如下: public static DefaultTableModel DTM=null; //Vector中: //一个放标题,一个放内容 //>表示只接受集合的类型 Vector biaoTi; Vector> neiRong; public swingBiaoGe(){ this.setLayout(null); this.setSize(600,600); this.setLocationRelativeTo(null); //给标题赋值: biaoTi=new Vector(); biaoTi.add("编号");biaoTi.add("姓名"); biaoTi.add("性别");biaoTi.add("年龄"); //给内容赋值: neiRong=new Vector>(); for(int i=0;i<5;i++){ Vector v=new Vector(); v.add("编号"+(i+6));v.add("诗书画唱"+(i+6)); v.add("性别"+(i+6));v.add("年龄"+(i+6)); neiRong.add(v); } //将内容添加到装载内容的容器中: DTM=new DefaultTableModel(neiRong,biaoTi); DTM=new DefaultTableModel(neiRong,biaoTi) { @Override public boolean isCellEditable(int a, int b) { return false; } }; biaoGe=new JTable(DTM); //设置滚动条: JScrollPane jsp=new JScrollPane(biaoGe); jsp.setBounds(10,10,400,400); this.add(jsp); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } JTable初始化数据,数据要求链接JDBC获取 create database yonghu select from shangpin; select from sp_Type; create table sp_Type( sp_TypeID int primary key identity(1,1), sp_TypeName varchar(100) not null ); insert into sp_Type values('水果'); insert into sp_Type values('零食'); insert into sp_Type values('小吃'); insert into sp_Type values('日常用品'); create table shangpin( sp_ID int primary key identity(1,1), sp_Name varchar(100) not null, sp_Price decimal(10,2) not null, sp_TypeID int, sp_Jieshao varchar(300) ); insert into shangpin values('苹果',12,1,'好吃的苹果'); insert into shangpin values('香蕉',2,1,'好吃的香蕉'); insert into shangpin values('橘子',4,1,'好吃的橘子'); insert into shangpin values('娃哈哈',3,2,'好吃营养好'); insert into shangpin values('牙刷',5,4,'全自动牙刷'); package SwingJdbc; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Vector; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.table.DefaultTableModel; public class biaoGe extends JFrame { class shiJian implements MouseListener, ActionListener { public biaoGe jieShou = null; public shiJian(biaoGe chuangTi) { this.jieShou = chuangTi; } @Override public void actionPerformed(ActionEvent arg0) { String name = jieShou.wenBenKuangName.getText(); String price = jieShou.wenBenKuangPrice.getText(); String type = jieShou.wenBenKuangTypeId.getText(); String jieshao = jieShou.wenBenKuangJieShao. getText(); String sql = "insert into shangpin values('" + name + "'" + ", " + price + "," + type + ",'" + jieshao + "')"; if (DBUtils.ZSG(sql)) { JOptionPane.showMessageDialog(null, "增加成功"); jieShou.chaxunchushihua(); } else { JOptionPane.showMessageDialog(null, "出现了未知的错误,增加失败"); } } @Override public void mouseClicked(MouseEvent arg0) { if (arg0.getClickCount() == 2) { int row = jieShou.biaoGe1.getSelectedRow(); jieShou.wenBenKuangBianHao .setText(jieShou.biaoGe1.getValueAt( row, 0).toString()); jieShou.wenBenKuangName .setText(jieShou.biaoGe1.getValueAt( row, 1).toString()); jieShou.wenBenKuangPrice .setText(jieShou.biaoGe1.getValueAt( row, 2).toString()); jieShou.wenBenKuangTypeId .setText(jieShou.biaoGe1.getValueAt( row, 3).toString()); jieShou.wenBenKuangJieShao .setText(jieShou.biaoGe1.getValueAt( row, 4).toString()); } if (arg0.isMetaDown()) { int num = JOptionPane.showConfirmDialog(null, "是否确认删除这条信息?"); if (num == 0) { int row = jieShou.biaoGe1 .getSelectedRow(); String sql = "delete shangpin where sp_id=" + jieShou.biaoGe1.getValueAt( row, 0) + ""; if (DBUtils.ZSG(sql)) { JOptionPane.showMessageDialog(null, "册除成功"); jieShou.chaxunchushihua(); } else { JOptionPane.showMessageDialog(null, "出现了未知的错误,请重试"); } } } } @Override public void mouseEntered(MouseEvent arg0) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent arg0) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent arg0) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent arg0) { // TODO Auto-generated method stub } } static JButton zengJiaAnNiu = null; static DefaultTableModel biaoGeMoXing1 = null; static JScrollPane gunDongTiao = null; static JTable biaoGe1 = null; static JLabel wenZiBianHao, wenZiName, wenZiPrice, wenZiTypeId, wenZiJieShao; static JTextField wenBenKuangBianHao, wenBenKuangName, wenBenKuangPrice, wenBenKuangTypeId, wenBenKuangJieShao; static Vector BiaoTiJiHe = null; static Vector> NeiRongJiHe = null; JPanel mianBan1, mianBan2 = null; public biaoGe() { this.setTitle("登录后的界面"); this.setSize(800, 600); this.setLayout(null); this.setLocationRelativeTo(null); wenZiBianHao = new JLabel("编号"); wenZiName = new JLabel("名称"); wenZiPrice = new JLabel("价格"); wenZiTypeId = new JLabel("类型ID"); wenZiJieShao = new JLabel("介绍"); zengJiaAnNiu = new JButton("添加数据"); zengJiaAnNiu.setBounds(530, 390, 100, 30); zengJiaAnNiu.addActionListener(new shiJian(this)); this.add(zengJiaAnNiu); wenZiBianHao.setBounds(560, 100, 70, 30); wenZiName.setBounds(560, 140, 70, 30); wenZiPrice.setBounds(560, 180, 70, 30); wenZiTypeId.setBounds(560, 220, 70, 30); wenZiJieShao.setBounds(560, 260, 70, 30); this.add(wenZiBianHao); this.add(wenZiName); this.add(wenZiPrice); this.add(wenZiTypeId); this.add(wenZiJieShao); wenBenKuangBianHao = new JTextField(); wenBenKuangBianHao.setEditable(false); wenBenKuangName = new JTextField(); wenBenKuangPrice = new JTextField(); wenBenKuangTypeId = new JTextField(); wenBenKuangJieShao = new JTextField(); wenBenKuangBianHao.setBounds(640, 100, 130, 30); wenBenKuangName.setBounds(640, 140, 130, 30); wenBenKuangPrice.setBounds(640, 180, 130, 30); wenBenKuangTypeId.setBounds(640, 220, 130, 30); wenBenKuangJieShao.setBounds(640, 260, 130, 30); this.add(wenBenKuangBianHao); this.add(wenBenKuangName); this.add(wenBenKuangPrice); this.add(wenBenKuangTypeId); this.add(wenBenKuangJieShao); biaoGeFengZhuangFangFa(); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } //biaoGeFengZhuangFangFa表格的封装方法 private void biaoGeFengZhuangFangFa() { BiaoTiJiHe = new Vector(); BiaoTiJiHe.add("编号"); BiaoTiJiHe.add("名称"); BiaoTiJiHe.add("价格"); BiaoTiJiHe.add("类型"); BiaoTiJiHe.add("介绍"); String sql = "select from shangpin"; ResultSet res = DBUtils.Select(sql); try { NeiRongJiHe = new Vector>(); while (res.next()) { Vector v = new Vector(); v.add(res.getInt("sp_ID")); v.add(res.getString("sp_Name")); v.add(res.getDouble("sp_price")); v.add(res.getInt("sp_TypeID")); v.add(res.getString("sp_Jieshao")); NeiRongJiHe.add(v); } biaoGeMoXing1 = new DefaultTableModel(NeiRongJiHe, BiaoTiJiHe) { @Override public boolean isCellEditable(int a, int b) { return false; } }; biaoGe1 = new JTable(biaoGeMoXing1); biaoGe1.addMouseListener(new shiJian(this)); biaoGe1.setBounds(0, 0, 500, 500); gunDongTiao= new JScrollPane(biaoGe1); gunDongTiao .setBounds(0, 0, 550, 150); mianBan1 = new JPanel(); mianBan1.add(gunDongTiao ); mianBan1.setBounds(0, 0, 550, 250); this.add(mianBan1); } catch (SQLException e) { e.printStackTrace(); } } public void chaxunchushihua() { if (this.mianBan1 != null) { this.remove(mianBan1); } biaoGeFengZhuangFangFa(); // 释放资源:this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } package SwingJdbc; import java.sql.; public class DBUtils { static Connection con=null; static Statement sta=null; static ResultSet res=null; //在静态代码块中执行 static{ try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //封装链接数据库的方法 public static Connection getCon(){ if(con==null){ try { con=DriverManager.getConnection ("jdbc:sqlserver://localhost;databaseName=yonghu","qqq","123"); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return con; } //查询的方法 public static ResultSet Select(String sql){ con=getCon();//建立数据库链接 try { sta=con.createStatement(); res=sta.executeQuery(sql); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return res; } //增删改查的方法 //返回int类型的数据 public static boolean ZSG(String sql){ con=getCon();//建立数据库链接 boolean b=false; try { sta=con.createStatement(); int num=sta.executeUpdate(sql); //0就是没有执行成功,大于0 就成功了 if(num>0){ b=true; } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return b; } } package SwingJdbc; public class mains { public static void main(String[] args) { new biaoGe(); } } 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_39929646/article/details/114190817。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-01-18 08:36:23
525
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 http://bdonline.sqe.com/ 一个关于网站测试方面的网页,对这方面感兴趣的人可以参考 http://citeseer.nj.nec.com/ 一个丰富的电子书库,内容很多,而且提供著作的相关文档参考和下载,是作者非常推荐的一个资料参考网站 http://groups.yahoo.com/group/LoadRunner 性能测试工具LoadRunner的一个论坛 http://groups.yahoo.com/grorp/testing-paperannou-nce/messages 提供网站上当前发布的软件测试资料列表 http://satc.gsfc.nasa.gov/homepage.html 软件保证中心是美国国家航天局(NASA)投资设立的一个软件可靠性和安全性研究中心,研究包括了度量、工具、风险等各个方面 http://seg.iit.nrc.ca/English/index.html 加拿大的一个研究软件工程质量方面的组织,可以提供研究论文的下载 http://sepo.nosc.mil 内容来自美国SAN DIEGO的软件工程机构(Sofrware Engineering Process Office)主页,包括软件工程知识方面的资料 http://www.asq.org/ 是世界上最大的一个质量团体组织之一,有着比较丰富的论文资源,不过是收费的 http://www.automated-testing.com/ 一个自动化软件测试和自然语言处理研究页面,属于个人网页,上面有些资源可供下载 http://www.benchmarkresources.com/ 提供有关标杆方面的资料,也有一些其它软件测试方面的资料 http://www.betasoft.com/ 包含一些流行测试工具的介绍、下载和讨论,还提供测试方面的资料 http://www.brunel.ac.uk/~csstmmh2/vast/home.html VASTT研究组织,主要从事通过切片技术、测试技术和转换技术来验证和分析系统,对这方面技术感兴趣的人是可以在这里参考一些研究的项目及相关的一些主题信息 http://www.cc.gatech.edu/aristotle/ Aristole研究组织,研究软件系统分析、测试和维护等方面的技术,在测试方面的研究包括了回归测试、测试套最小化、面向对象软件测试等内容,该网站有丰富的论文资源可供下载 http://www.computer.org/ IEEE是世界上最悠久,也是在最大的计算机社会团体,它的电子图书馆拥有众多计算机方面的论文资料,是研究计算机方面的一个重要资源参考来源 http://www.cs.colostate.edu/testing/ 可靠性研究网站,有一些可靠性方面的论文资料 http://www.cs.york.ac.uk/testsig/ 约克大学的测试专业兴趣研究组网页,有比较丰富的资料下载,内容涵盖了测试的多个方面,包括测试自动化、测试数据生成、面向对象软件测试、验证确认过程等 http://www.csr.ncl.ac.uk/index.html 学校里面的一个软件可靠性研究中心,提供有关软件可靠性研究方面的一些信息和资料,对这方面感兴趣的人可以参考 http://www.dcs.shef.ac.uk/research/groups/vt/ 学校里的一个验证和测试研究机构,有一些相关项目和论文可供参考 http://www.esi.es/en/main/ ESI(欧洲软件组织),提供包括CMM评估方面的各种服务 http://www.europeindia.org/cd02/index.htm 一个可靠性研究网站,有可靠性方面的一些资料提供参考 http://www.fortest.org.uk/ 一个测试研究网站,研究包括了静态测试技术(如模型检查、理论证明)和动态测试(如测试自动化、特定缺陷的检查、测试有效性分析等) http://www.grove.co.uk/ 一个有关软件测试和咨询机构的网站,有一些测试方面的课程和资料供下载 http://www.hq.nasa.gov/office/codeq/relpract/prcls-23.htm NASA可靠性设计实践资料 http://www.io.com/~wazmo/ Bret Pettichord的主页,他的一个热点测试页面连接非常有价值,从中可以获得相当大的测试资料,很有价值 http://www.iso.ch/iso/en/ISOOnline.frontpage 国际标准化组织,提供包括ISO标准系统方面的各类参考资料 http://www.isse.gmu.edu/faculty/ofut/classes/ 821-ootest/papers.html 提供面向对象和基于构架的测试方面著作下载,对这方面感兴趣的读者可以参考该网站,肯定有价值 http://www.ivv.nasa.gov/ NASA设立的独立验证和确认机构,该机构提出了软件开发的全面验证和确认,在此可以获得这方面的研究资料 http://www.kaner.com/ 著名的测试专家Cem Kanner的主页,里面有许多关于测试的专题文章,相信对大家都有用。Cem Kanner关于测试的最著名的书要算Testing Software,这本书已成为一个测试人员的标准参考书 http://www.library.cmu.edu/Re-search/Engineer-ingAndSciences/CS+ECE/index.html 卡耐基梅陇大学网上图书馆,在这里你可以获得有关计算机方面各类论文资料,内容极其庞大,是研究软件测试不可获取的资料来源之一 http://www.loadtester.com/ 一个性能测试方面的网站,提供有关性能测试、性能监控等方面的资源,包括论文、论坛以及一些相关链接 http://www.mareinig.ch/mt/index.html 关于软件工程和应用开发领域的各种免费的实践知识、时事信息和资料文件下载,包括了测试方面的内容 http://www.mtsu.ceu/-storm/ 软件测试在线资源,包括提供目前有哪些人在研究测试,测试工具列表连接,测试会议,测试新闻和讨论,软件测试文学(包括各种测试杂志,测试报告),各种测试研究组织等内容 http://www.psqtcomference.com/ 实用软件质量技术和实用软件测试技术国际学术会议宣传网站,每年都会举行两次 http://www.qacity.com/front.htm 测试工程师资源网站,包含各种测试技术及相关资料下载 http://www.qaforums.com/ 关于软件质量保证方面的一个论坛,需要注册 http://www.qaiusa.com/ QAI是一个提供质量保证方面咨询的国际著名机构,提供各种质量和测试方面证书认证 http://www.qualitytree.com/ 一个测试咨询提供商,有一些测试可供下载,有几篇关于缺陷管理方面的文章值得参考 http://www.rational.com/ IBM Rational的官方网站,可以在这里寻找测试方面的工具信息。IBM Rational提供测试方面一系列的工具,比较全面 http://rexblackconsulting.com/Pages/publicat-ions.htm Rex Black的个人主页,有一些测试和测试管理方面的资料可供下载 http://www.riceconsulting.com/ 一个测试咨询提供商,有一些测试资料可供下载,但不多 http://www.satisfice.com/ 包含James Bach关于软件测试和过程方面的很多论文,尤其在启发式测试策略方面值得参考 http://www.satisfice.com/seminars.shtml 一个黑盒软件测试方面的研讨会,主要由测试专家Cem Kanar和James Bach组织,有一些值得下载的资料 http://www.sdmagazine.com/ 软件开发杂志,经常会有一些关于测试方面好的论文资料,同时还包括了项目和过程改进方面的课题,并且定期会有一些关于质量和测试方面的问题讨论 http://www.sei.cmu.edu/ 著名的软件工程组织,承担美国国防部众多软件工程研究项目,在这里你可以获俄各类关于工程质量和测试方面的资料。该网站提供强有力的搜索功能,可以快速检索到你想要的论文资料,并且可以免费下载 http://www.soft.com/Institute/HotList/ 提供了网上软件质量热点连接,包括:专业团体组织连接、教育机构连接、商业咨询公司连接、质量相关技术会议连接、各类测试技术专题连接等 http://www.soft.com/News/QTN-Online/ 质量技术时事,提供有关测试质量方面的一些时事介绍信息,对于关心测试和质量发展的人士来说是很有价值的 http://www.softwaredioxide.com/ 包括软件工程(CMM,CMMI,项目管理)软件测试等方面的资源 http://www.softwareqatest.com/ 软件质量/测试资源中心。该中心提供了常见的有关测试方面的FAQ资料,各质量/测试网站介绍,各质量/测试工具介绍,各质量/策划书籍介绍以及与测试相关的工作网站介绍 http://www.softwaretestinginstitute.com 一个软件测试机构,提供软件质量/测试方面的调查分析,测试计划模板,测试WWW的技术,如何获得测试证书的指导,测试方面书籍介绍,并且提供了一个测试论坛 http://www.sqatester.com/index.htm 一个包含各种测试和质量保证方面的技术网站,提供咨询和培训服务,并有一些测试人员社团组织,特色内容是缺陷处理方面的技术 http://www.sqe.com/ 一个软件质量工程服务性网站,组织软件测试自动化、STAR-EASE、STARWEST等方面的测试学术会议,并提供一些相关信息资料和课程服务 http://www.stickyminds.com/ 提供关于软件测试和质量保证方面的当前发展信息资料,论文等资源 http://www.stqemagazine.com/ 软件策划和质量工程杂志,经常有一些好的论文供下载,不过数量较少,更多地需要通过订购获得,内容还是很有价值的 http://www.tantara.ab.ca/ 软件质量方面的一个咨询网站,有过程改进方面的一些资料提供 http://www.tcse.org/ IEEE的一个软件工程技术委员会,提供技术论文下载,并有一个功能强大的分类下载搜索功能,可以搜索到测试类型、测试管理、 测试分析等各方面资料 http://www.testing.com/ 测试技术专家Brain Marick的主页,包含了Marick 研究的一些资料和论文,该网页提供了测试模式方面的资料,值得研究。总之,如果对测试实践感兴趣,该网站一定不能错过 http://www.testingcenter.com/ 有一些测试方面的课程体系,有一些价值 http://www.testingconferences.com/asiastar/home 著名的AsiaStar测试国际学术会议官方网站,感兴趣的人一定不能错过 http://www.testingstuff.com/ Kerry Zallar的个人主页,提供一些有关培训、工具、会议、论文方面的参考信息 http://www-sqi.cit.gu.edu.au/ 软件质量机构,有一些技术资料可以供下载,包括软件产品质量模型、再工程、软件质量改进等 这里有些网站已经不能使用了. 转载于:https://www.cnblogs.com/mmsky/p/4581975.html 本篇文章为转载内容。原文链接:https://blog.csdn.net/aizongzhuang2281/article/details/101129638。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-08-29 09:17:46
134
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 相关阅读: 阿里云Redis开发规范 千万级规模高性能、高并发的网络架构经验分享 互联网技术(java框架、分布式、集群)干货视频大全,不看后悔!(免费下载) 本文转自:公众号老板思维与智库(ID:laobanzhiku88),欢迎大家关注 笔者搬家前有个邻居,两口子典型的中年夫妻。 时不时由着一些鸡毛蒜皮的小事突然爆发争吵,但为了孩子老人和自己的颜面又要在人前假装和睦。 吵架的内容无非几样,孩子学业、老人赡养... 以及,丈夫人到中年,却还只是个普普通通的员工,业绩上不高不低,不至于垫底,也不足以升迁,家庭经济压力不小。 老话说,贫贱夫妻百事衰,一点没错。 一生压力最大的时期无非上有老下有小的中年。 事业上年纪已经失去了竞争力,脑力体力精力都比不过后来的年轻人。 无数的争吵、矛盾、压力,说明白点,大都来自于经济上的缺乏。 这样的家庭在中国并不少见。 扪心自问,兢兢业业十几年,没有功劳也有苦劳,为什么现在还只是个普通员工? 甚至比自己晚入行几年的新人都早早升迁小有成就了。 无目标无计划 大部分到了中年仍旧一事无成的人多在年轻时对自己的人生没有长远的规划。 年纪轻轻就失去梦想,只想当咸鱼。 做一天和尚撞一天钟,不知不觉,最适合奋斗的那几年都在这种平淡中弹指一挥间,回过神来人已经不惑之年。 普通员工不可怕,可怕的是你是个没有自己“小目标”的普通员工。 过度满足于现状只会增加你的职场生存隐患,很可能老板没有开除你单单念在你勤恳付出多年的三分情面上。 但是仅仅不犯过错不应该成为工作的准则。 都说学如逆水行舟,只要处在不断前进的社会里,人就要努力向前,才不至于被抛在人后。 原地停留,不过是变相的倒退罢了。 无论青年还是中年,当着手当下,给自己定下前行的目标,不断寻求突破与进展。 人要做的,是永远比昨天的自己更优秀。 实际行动力差 笔者接触到的中年人,大部分实际行动力都不强。 说起人生道理、励志格言他们如数家珍,一说一箩筐,分分钟能登台做演讲。 但真真切切落实到实际行动里,完全又是另外一回事。 具体到某一件事的时候,他们会有各种各样的理由来拒绝改变和行动。 好似他们的境况永远特殊,永远比别人更加糟糕,旁人永远难以体会。 常听朋友抱怨起他的父亲,说父亲年轻时喜欢钓鱼,偶尔也会在周末带他出去垂钓。 这本是极好的一项爱好,修身养性还能给餐桌添些鲜味。 但随着他的长大,父亲步入中年,钓鱼这项活动就只存在于父亲和外人的谈天说地里。 当他邀请父亲一同出门垂钓的时候,总是被各种理由拒绝。 那可能是伯父真的有重要的事情要做嘛,笔者笑道。 朋友无奈直摇头,他给我的理由无非几样。 要么是嫌钓鱼地方不好,找到了好地方又嫌路途远,两者都不错的又说天气不适合,林林总总说起来无非就三个字,不想动。 一件自己喜欢的事都不愿意花时间去享受,更不用说繁琐的工作了。 再高的思想觉悟、再充分的理论知识,没有实战,终究不过是纸上谈兵,虚吹一场,没有任何实际效用。 脚踏实地,踏踏实实做实事,才可能有收获。 不懂得投资自己 股神巴菲特在《福布斯》杂志的采访中说道,有一种投资好过其他所有的投资,那就是投资自己。 没有人能夺走你自身学到的东西,每个人都有这样的投资潜力。 无论处在什么阶段,保持学习都是十分重要的一件事。 工作的十几年间,为什么别人都升职了自己却留在原地? 常常会疑惑,刚进公司的时候也是优秀的潜力股一枚,升职的时候老板怎么就看不见我? 很简单,因为潜力股要经过挖掘投资才能成为优质股。 人就像一方活水,有源源不断的补给才能保持自身不干涸,才能掀得起浪花。 不断增加自己的学识、磨练出过硬的技能,在职场中你的综合考察才会不断加分! 不懂的投资自己,提升能力,只会让你被淘汰的更快。 心态老得比身体快 明明还是个中年人,精神面貌看着还不如小区里跳广场舞的大妈大爷们。 整个人的心态衰老程度已经远远超过身体的衰老程度。 从内里散发出消极颓废的负能量。 试想谁会把重要的工作交给一个丧气满满的人呢? 职场上的中年人在做事的时候难免受家庭、他人眼光、年龄的牵绊,畏手畏脚,瞻前顾后。 他们总在想,我这样做,会显得自己过于出彩,会畏惧别人“一把年纪还想出风头”的闲言碎语和轻信别人“老了老了,都是年轻人的天下”的衰言败语。 妈妈常教导我,让我养成良好习惯。这样长大才能成为一个有用的人。良好的习惯是尊敬师长这样长大才能成为一个有用的人。良好的习惯是尊敬师长,爱护同学,对人有礼貌;是不粗心,做事情不拖拉;还是爱护公物,不浪费粮食。为什么呢?因为拥有良好习惯,做一个品德高尚的人,懂得尊重别人,才会得到别人的尊重。我要努力地做到这些。我有一些坏习惯,有时候学习很粗心,把一些会做的题做错。在生活上,也很粗心,有一次早上起床居然穿反了衣服。我吃饭很慢,有的时候还剩饭。我还起床磨蹭,本来应该迅速地穿好衣服,但是,我总是磨磨蹭蹭地,速度很慢。“我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!” 在上幼儿园以前,我什么也不会干,就连穿衣服也是妈妈给我穿好,就要上幼儿园了,这样可不行,妈妈锻炼我要学会自己穿衣服。 有一天,妈妈把衣服摆在我面前,开始让我自己穿。一开始。我又哭又叫就是不穿,还把衣服扔的满地都是,然后坐在地上开始大哭,等了好长时间,妈妈还是不理我,我只好自己乖乖的把衣服穿好, 一出了房间门,妈妈就笑了起来,再看看我的衣服,毛衣和裤子都穿反了,我赶紧回房间又重新穿了一遍,这次穿好了,拿起外套,可是外套的扣子又扣不上了,扣子可调皮了,好像故意和我作对,我把扣子往扣眼——人类邪恶的根源;爱情——幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话:幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话“亲爱的!擦干你的眼泪,至高无上的爱情已经打开了我们的眼界,使我们成了它的崇拜者。是它, 妈妈常教导我,让我养成良好习惯。这样长大才能成为一个有用的人。良好的习惯是尊敬师长这样长大才能成为一个有用的人。良好的习惯是尊敬师长,爱护同学,对人有礼貌;是不粗心,做事情不拖拉;还是爱护公物,不浪费粮食。为什么呢?因为拥有良好习惯,做一个品德高尚的人,懂得尊重别人,才会得到别人的尊重。我要努力地做到这些。我有一些坏习惯,有时候学习很粗心,把一些会做的题做错。在生活上,也很粗心,有一次早上起床居然穿反了衣服。我吃饭很慢,有的时候还剩饭。我还起床磨蹭,本来应该迅速地穿好衣服,但是,我总是磨磨蹭蹭地,速度很慢。“我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!我打算在这学期里,改掉这些坏习惯。早上起来,迅速地穿好衣服,不拖拉。学习不粗心,仔细完成每一道题。吃饭的时候,要很快的把饭吃完,不剩饭。我要从一点一滴做起,逐渐养成良好习惯。我相信自己一定能成为一名品学兼优的好学生!” 在上幼儿园以前,我什么也不会干,就连穿衣服也是妈妈给我穿好,就要上幼儿园了,这样可不行,妈妈锻炼我要学会自己穿衣服。 有一天,妈妈把衣服摆在我面前,开始让我自己穿。一开始。我又哭又叫就是不穿,还把衣服扔的满地都是,然后坐在地上开始大哭,等了好长时间,妈妈还是不理我,我只好自己乖乖的把衣服穿好, 一出了房间门,妈妈就笑了起来,再看看我的衣服,毛衣和裤子都穿反了,我赶紧回房间又重新穿了一遍,这次穿好了,拿起外套,可是外套的扣子又扣不上了,扣子可调皮了,好像故意和我作对,我把扣子往扣眼——人类邪恶的根源;爱情——幸福和光明的源泉。我一直在这些思想的舞台上徘徊。突然我发现两个身影从我面前经过,坐在不远的草地上。这是一对从农田那边走过来的青年男女。农田那边有农民的茅舍。在一阵令人伤心的沉默之后,随着一声长叹,我听见从一个肺痨病人的嘴里说出了这样的话:“亲爱的!擦干你的眼泪,至高无上的爱情已经打开了我们的眼界,使我们成了它的崇拜者。是它, 每一个碌碌无为的中年人都改明白的一个道理是,职场所谓的新人老人,取决于你的成就,而不是入行时间。 入行十余年还不如别人入行三五年来的专业,所谓老人不过是虚谈。 只要一天还出成绩,对待工作就当保持一个新人该有的拼劲和争上游的心态,抛开顾虑,努力向前便是! -END- 声明:本文属于老板思维与智库(ID:laobanzhiku88),图片来源于网络 看完本文有收获?请转发分享给更多人 欢迎关注“互联网架构师”,我们分享最有价值的互联网技术干货文章,助力您成为有思想的全栈架构师,我们只聊互联网、只聊架构,不聊其他!打造最有价值的架构师圈子和社区。 本公众号覆盖中国主要首席架构师、高级架构师、CTO、技术总监、技术负责人等人 群。分享最有价值的架构思想和内容。打造中国互联网圈最有价值的架构师圈子。 长按下方的二维码可以快速关注我们 如想加群讨论学习,请点击右下角的“加群学习”菜单入群 本篇文章为转载内容。原文链接:https://blog.csdn.net/emprere/article/details/98859913。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-06-29 14:16:29
119
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 windows实用键盘快捷键 一、ctrl相关 二、alt、shift相关 三、win(windows徽标的简称)相关 四、其他快捷键 五、运行窗口快捷命令 先输入win+ R 六、小结 一、ctrl相关 Ctrl + X -> 剪切选定项 Ctrl + C(或 Ctrl + Insert) -> 复制选定项 Ctrl + V(或 Shift + Insert) -> 粘贴选定项 Ctrl + Z -> 撤消操作 Ctrl + Esc -> 打开“开始”屏幕 Ctrl + Shift + Esc -> 打开任务管理器 Ctrl + Shift -> 在提供了多个键盘布局时切换键盘布局 Ctrl + 空格键 -> 打开或关闭中文输入法编辑器 (IME) 二、alt、shift相关 Alt + Tab -> 在打开的应用之间切换 Alt + F4 -> 关闭活动项,或者退出活动应用 Shift + F10 -> 显示选定项的快捷菜单 Shift 加任意箭头键 -> 在窗口中或桌面上选择多个项目,或者在文档中选择文本 Shift + Delete -> 无需先将选定项移动到“回收站”,直接将其删除 三、win(windows徽标的简称)相关 win + L -> 锁定电脑 win + D -> 显示和隐藏桌面 win + E -> 打开“文件资源管理器” win + I -> 打开“设置” win + M -> 最小化所有窗口 win + Shift + M -> 将最小化的窗口还原到桌面 win + P -> 选择演示显示模式 win + K -> 打开“连接”快速操作 win + L -> 锁定电脑或切换帐户 win + Tab -> 打开“任务视图” win + R -> 打开运行窗口 四、其他快捷键 End -> 显示活动窗口的底端 Home -> 显示活动窗口的顶端 F11 -> 最大化或最小化活动窗口 五、运行窗口快捷命令 先输入win+ R 本小结转载地址:https://blog.csdn.net/qq_42402854/article/details/93162387 1.calc:启动计算器 2.appwiz.cpl:程序和功能 3.certmgr.msc:证书管理实用程序 4.charmap:启动字符映射表 5.chkdsk.exe:Chkdsk磁盘检查(管理员身份运行命令提示符) 6.cleanmgr: 打开磁盘清理工具 7.cliconfg:SQL SERVER 客户端网络实用工具 8.cmstp:连接管理器配置文件安装程序 9.cmd:CMD命令提示符 10.自动关机命令 Shutdown -s -t 600:表示600秒后自动关机 shutdown -a :可取消定时关机 Shutdown -r -t 600:表示600秒后自动重启 rundll32 user32.dll,LockWorkStation:表示锁定计算机 11.colorcpl:颜色管理,配置显示器和打印机等中的色彩 12.CompMgmtLauncher:计算机管理 13.compmgmt.msc:计算机管理 14.credwiz:备份或还原储存的用户名和密码 15.comexp.msc:打开系统组件服务 16.control:控制面版 17.dcomcnfg:打开系统组件服务 18.Dccw:显示颜色校准 19.devmgmt.msc:设备管理器 20.desk.cpl:屏幕分辨率 21.dfrgui:优化驱动器 Windows 7→dfrg.msc:磁盘碎片整理程序 22.dialer:电话拨号程序 23.diskmgmt.msc:磁盘管理 24.dvdplay:DVD播放器 25.dxdiag:检查DirectX信息 26.eudcedit:造字程序 27.eventvwr:事件查看器 28.explorer:打开资源管理器 29.Firewall.cpl:Windows防火墙 30.FXSCOVER:传真封面编辑器 31.fsmgmt.msc:共享文件夹管理器 32.gpedit.msc:组策略 33.hdwwiz.cpl:设备管理器 34.inetcpl.cpl:Internet属性 35.intl.cpl:区域 36.iexpress:木马捆绑工具,系统自带 37.joy.cpl:游戏控制器 38.logoff:注销命令 39.lusrmgr.msc:本地用户和组 40.lpksetup:语言包安装/删除向导,安装向导会提示下载语言包 41.lusrmgr.msc:本机用户和组 42.main.cpl:鼠标属性 43.mmsys.cpl:声音 44.magnify:放大镜实用程序 45.mem.exe:显示内存使用情况(如果直接运行无效,可以先管理员身份运行命令提示符,在命令提示符里输入mem.exe>d:a.txt 即可打开d盘查看a.txt,里面的就是内存使用情况了。当然什么盘什么文件名可自己决定。) 46.MdSched:Windows内存诊断程序 47.mmc:打开控制台 48.mobsync:同步命令 49.mplayer2:简易widnows media player 50.Msconfig.exe:系统配置实用程序 51.msdt:微软支持诊断工具 52.msinfo32:系统信息 53.mspaint:画图 54.Msra:Windows远程协助 55.mstsc:远程桌面连接 56.NAPCLCFG.MSC:客户端配置 57.ncpa.cpl:网络连接 58.narrator:屏幕“讲述人” 59.Netplwiz:高级用户帐户控制面板,设置登陆安全相关的选项 60.netstat : an(TC)命令检查接口 61.notepad:打开记事本 62.Nslookup:IP地址侦测器 63.odbcad32:ODBC数据源管理器 64.OptionalFeatures:打开“打开或关闭Windows功能”对话框 65.osk:打开屏幕键盘 66.perfmon.msc:计算机性能监测器 67.perfmon:计算机性能监测器 68.PowerShell:提供强大远程处理能力 69.printmanagement.msc:打印管理 70.powercfg.cpl:电源选项 71.psr:问题步骤记录器 72.Rasphone:网络连接 73.Recdisc:创建系统修复光盘 74.Resmon:资源监视器 75.Rstrui:系统还原 76.regedit.exe:注册表 77.regedt32:注册表编辑器 78.rsop.msc:组策略结果集 79.sdclt:备份状态与配置,就是查看系统是否已备份 80.secpol.msc:本地安全策略 81.services.msc:本地服务设置 82.sfc /scannow:扫描错误并复原/windows文件保护 83.sfc.exe:系统文件检查器 84.shrpubw:创建共享文件夹 85.sigverif:文件签名验证程序 86.slui:Windows激活,查看系统激活信息 87.slmgr.vbs -dlv :显示详细的许可证信息 88.snippingtool:截图工具,支持无规则截图 89.soundrecorder:录音机,没有录音时间的限制 90.StikyNot:便笺 91.sysdm.cpl:系统属性 92.sysedit:系统配置编辑器 93.syskey:系统加密,一旦加密就不能解开,保护系统的双重密码 94.taskmgr:任务管理器(旧版) 95.TM任务管理器(新版) 96.taskschd.msc:任务计划程序 97.timedate.cpl:日期和时间 98.UserAccountControlSettings用户账户控制设置 99.utilman:辅助工具管理器 100.wf.msc:高级安全Windows防火墙 101.WFS:Windows传真和扫描 102.wiaacmgr:扫描仪和照相机向导 103.winver:关于Windows 104.wmimgmt.msc:打开windows管理体系结构(WMI) 105.write:写字板 106.wscui.cpl:操作中心 107.wuapp:Windows更新 108.wscript:windows脚本宿主设置 六、小结 键盘快捷键会大大提高使用效率,让你在外行面前显得更酷。持续更新中…感谢点赞,评论与转发,谢谢! 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_44168588/article/details/121208530。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-02-01 13:38:26
91
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 目录 1. 作者介绍 2. 算法介绍 2.1 阿里云介绍 2.2 证件照生成背景 2.3 图像分割算法 3.调用阿里云API进行证件照生成实例 3.1 准备工作 3.2 实验代码 3.3 实验结果与分析 参考(可供参考的链接和引用文献) 1. 作者介绍 王逸腾,男,西安工程大学电子信息学院,2022级硕士研究生 研究方向:三维手部姿态和网格估计 电子邮件:2978558373@qq.com 路治东,男,西安工程大学电子信息学院,2022级研究生,张宏伟人工智能课题组 研究方向:机器视觉与人工智能 电子邮件:2063079527@qq.com 2. 算法介绍 2.1 阿里云介绍 阿里云创立于2009年,是全球领先的云计算及人工智能科技公司,致力于以在线公共服务的方式,提供安全、可靠的计算和数据处理能力,让计算和人工智能成为普惠科技。阿里云服务着制造、金融、政务、交通、医疗、电信、能源等众多领域的领军企业,包括中国联通、12306、中石化、中石油、飞利浦、华大基因等大型企业客户,以及微博、知乎、锤子科技等明星互联网公司。在天猫双11全球狂欢节、12306春运购票等极富挑战的应用场景中,阿里云保持着良好的运行纪录 阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本 猿辅导、中泰证券、小米、媛福达、Soul和当贝,这些我们耳熟能详的APP或企业中,阿里云给他们提供了性能强大、安全、稳定的云产品与服务。 计算,容器,存储,网络与CDN,安全、中间件、数据库、大数据计算、人工智能与机器学习、媒体服务、企业服务与云通信、物联网、开发工具、迁移与运维管理和专有云等方面,阿里云都做的很不错。 2.2 证件照生成背景 传统做法:通常是人工进行P图,不仅费时费力,而且效果也很难保障,容易有瑕疵。 机器学习做法:通常利用边缘检测算法进行人物轮廓提取。 深度学习做法:通常使用分割算法进行人物分割。例如U-Net网络。 2.3 图像分割算法 《BiHand: Recovering Hand Mesh with Multi-stage Bisected Hourglass Networks》里的SeedNet网络是很经典的网络,它把分割任务转变成多个任务。作者的思想是:尽可能的通过多任务学习收拢语义,这样或许会分割的更好或姿态估计的更好。其实这个模型就是多阶段学习网络的一部分,作者想通过中间监督来提高网络的性能。 我提取bihand网络中的SeedNet与训练权重,进行分割结果展示如下 我是用的模型不是全程的,是第一阶段的。为了可视化出最好的效果,我把第一阶段也就是SeedNet网络的输出分别采用不同的方式可视化。 从左边数第一张图为原图,第二张图为sigmoid后利用plt.imshow(colored_mask, cmap=‘jet’)进行彩色映射。第三张图为网络输出的张量经过sigmoid后,二色分割图,阀闸值0.5。第四张为网络的直接输出,利用直接产生的张量图进行颜色映射。第五张为使用sigmoid处理张量后进行的颜色映射。第六张为使用sigmoid处理张量后进行0,1分割掩码映射。使用原模型和网络需要添加很多代码。下面为修改后的的代码: 下面为修改后的net_seedd代码: Copyright (c) Lixin YANG. All Rights Reserved.r"""Networks for heatmap estimation from RGB images using Hourglass Network"Stacked Hourglass Networks for Human Pose Estimation", Alejandro Newell, Kaiyu Yang, Jia Deng, ECCV 2016"""import numpy as npimport torchimport torch.nn as nnimport torch.nn.functional as Ffrom skimage import io,transform,utilfrom termcolor import colored, cprintfrom bihand.models.bases.bottleneck import BottleneckBlockfrom bihand.models.bases.hourglass import HourglassBisectedimport bihand.utils.func as funcimport matplotlib.pyplot as pltfrom bihand.utils import miscimport matplotlib.cm as cmdef color_mask(output_ok): 颜色映射cmap = plt.cm.get_cmap('jet') 将张量转换为numpy数组mask_array = output_ok.detach().numpy() 创建彩色图像cmap = cm.get_cmap('jet')colored_mask = cmap(mask_array)return colored_mask 可视化 plt.imshow(colored_mask, cmap='jet') plt.axis('off') plt.show()def two_color(mask_tensor): 将张量转换为numpy数组mask_array = mask_tensor.detach().numpy() 将0到1之间的值转换为二值化掩码threshold = 0.5 阈值,大于阈值的为白色,小于等于阈值的为黑色binary_mask = np.where(mask_array > threshold, 1, 0)return binary_mask 可视化 plt.imshow(binary_mask, cmap='gray') plt.axis('off') plt.show()class SeedNet(nn.Module):def __init__(self,nstacks=2,nblocks=1,njoints=21,block=BottleneckBlock,):super(SeedNet, self).__init__()self.njoints = njointsself.nstacks = nstacksself.in_planes = 64self.conv1 = nn.Conv2d(3, self.in_planes, kernel_size=7, stride=2, padding=3, bias=True)self.bn1 = nn.BatchNorm2d(self.in_planes)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(2, stride=2)self.layer1 = self._make_residual(block, nblocks, self.in_planes, 2self.in_planes) current self.in_planes is 64 2 = 128self.layer2 = self._make_residual(block, nblocks, self.in_planes, 2self.in_planes) current self.in_planes is 128 2 = 256self.layer3 = self._make_residual(block, nblocks, self.in_planes, self.in_planes)ch = self.in_planes 256hg2b, res1, res2, fc1, _fc1, fc2, _fc2= [],[],[],[],[],[],[]hm, _hm, mask, _mask = [], [], [], []for i in range(nstacks): 2hg2b.append(HourglassBisected(block, nblocks, ch, depth=4))res1.append(self._make_residual(block, nblocks, ch, ch))res2.append(self._make_residual(block, nblocks, ch, ch))fc1.append(self._make_fc(ch, ch))fc2.append(self._make_fc(ch, ch))hm.append(nn.Conv2d(ch, njoints, kernel_size=1, bias=True))mask.append(nn.Conv2d(ch, 1, kernel_size=1, bias=True))if i < nstacks-1:_fc1.append(nn.Conv2d(ch, ch, kernel_size=1, bias=False))_fc2.append(nn.Conv2d(ch, ch, kernel_size=1, bias=False))_hm.append(nn.Conv2d(njoints, ch, kernel_size=1, bias=False))_mask.append(nn.Conv2d(1, ch, kernel_size=1, bias=False))self.hg2b = nn.ModuleList(hg2b) hgs: hourglass stackself.res1 = nn.ModuleList(res1)self.fc1 = nn.ModuleList(fc1)self._fc1 = nn.ModuleList(_fc1)self.res2 = nn.ModuleList(res2)self.fc2 = nn.ModuleList(fc2)self._fc2 = nn.ModuleList(_fc2)self.hm = nn.ModuleList(hm)self._hm = nn.ModuleList(_hm)self.mask = nn.ModuleList(mask)self._mask = nn.ModuleList(_mask)def _make_fc(self, in_planes, out_planes):bn = nn.BatchNorm2d(in_planes)conv = nn.Conv2d(in_planes, out_planes, kernel_size=1, bias=False)return nn.Sequential(conv, bn, self.relu)def _make_residual(self, block, nblocks, in_planes, out_planes):layers = []layers.append( block( in_planes, out_planes) )self.in_planes = out_planesfor i in range(1, nblocks):layers.append(block( self.in_planes, out_planes))return nn.Sequential(layers)def forward(self, x):l_hm, l_mask, l_enc = [], [], []x = self.conv1(x) x: (N,64,128,128)x = self.bn1(x)x = self.relu(x)x = self.layer1(x)x = self.maxpool(x) x: (N,128,64,64)x = self.layer2(x)x = self.layer3(x)for i in range(self.nstacks): 2y_1, y_2, _ = self.hg2b[i](x)y_1 = self.res1[i](y_1)y_1 = self.fc1[i](y_1)est_hm = self.hm[i](y_1)l_hm.append(est_hm)y_2 = self.res2[i](y_2)y_2 = self.fc2[i](y_2)est_mask = self.mask[i](y_2)l_mask.append(est_mask)if i < self.nstacks-1:_fc1 = self._fc1[i](y_1)_hm = self._hm[i](est_hm)_fc2 = self._fc2[i](y_2)_mask = self._mask[i](est_mask)x = x + _fc1 + _fc2 + _hm + _maskl_enc.append(x)else:l_enc.append(x + y_1 + y_2)assert len(l_hm) == self.nstacksreturn l_hm, l_mask, l_encif __name__ == '__main__':a = torch.randn(10, 3, 256, 256) SeedNetmodel = SeedNet() output1,output2,output3 = SeedNetmodel(a) print(output1,output2,output3)total_params = sum(p.numel() for p in SeedNetmodel.parameters())/1000000print("Total parameters: ", total_params)pretrained_weights_path = 'E:/bihand/released_checkpoints/ckp_seednet_all.pth.tar'img_rgb_path=r"E:\FreiHAND\training\rgb\00000153.jpg"img=io.imread(img_rgb_path)resized_img = transform.resize(img, (256, 256), anti_aliasing=True)img256=util.img_as_ubyte(resized_img)plt.imshow(resized_img)plt.axis('off') 关闭坐标轴plt.show()''' implicit HWC -> CHW, 255 -> 1 '''img1 = func.to_tensor(img256).float() 转换为张量并且进行标准化处理''' 0-mean, 1 std, [0,1] -> [-0.5, 0.5] '''img2 = func.normalize(img1, [0.5, 0.5, 0.5], [1, 1, 1])img3 = torch.unsqueeze(img2, 0)ok=img3print(img.shape)SeedNetmodel = SeedNet()misc.load_checkpoint(SeedNetmodel, pretrained_weights_path)加载权重output1, output2, output3 = SeedNetmodel(img3)mask_tensor = torch.rand(1, 64, 64)output=output2[1] 1,1,64,64output_1=output[0] 1,64,64output_ok=torch.sigmoid(output_1[0])output_real=output_1[0].detach().numpy()直接产生的张量图color_mask=color_mask(output_ok) 显示彩色分割图two_color=two_color(output_ok)显示黑白分割图see=output_ok.detach().numpy() 使用Matplotlib库显示分割掩码 plt.imshow(see, cmap='gray') plt.axis('off') plt.show() print(output1, output2, output3)images = [resized_img, color_mask, two_color,output_real,see,see]rows = 1cols = 4 创建子图并展示图像fig, axes = plt.subplots(1, 6, figsize=(30, 5)) 遍历图像列表,并在每个子图中显示图像for i, image in enumerate(images):ax = axes[i] if cols > 1 else axes 如果只有一列,则直接使用axesif i ==5:ax.imshow(image, cmap='gray')else:ax.imshow(image)ax.imshowax.axis('off') 调整子图之间的间距plt.subplots_adjust(wspace=0.1, hspace=0.1) 展示图像plt.show() 上述的代码文件是在bihand/models/net_seed.py中,全部代码链接在https://github.com/lixiny/bihand。 把bihand/models/net_seed.p中的代码修改为我提供的代码即可使用作者训练好的模型和进行各种可视化。(预训练模型根据作者代码提示下载) 3.调用阿里云API进行证件照生成实例 3.1 准备工作 1.找到接口 进入下面链接即可快速访问 link 2.购买试用包 3.查看APPcode 4.下载代码 5.参数说明 3.2 实验代码 !/usr/bin/python encoding: utf-8"""===========================证件照制作接口==========================="""import requestsimport jsonimport base64import hashlibclass Idphoto:def __init__(self, appcode, timeout=7):self.appcode = appcodeself.timeout = timeoutself.make_idphoto_url = 'https://idp2.market.alicloudapi.com/idphoto/make'self.headers = {'Authorization': 'APPCODE ' + appcode,}def get_md5_data(self, body):"""md5加密:param body_json::return:"""md5lib = hashlib.md5()md5lib.update(body.encode("utf-8"))body_md5 = md5lib.digest()body_md5 = base64.b64encode(body_md5)return body_md5def get_photo_base64(self, file_path):with open(file_path, 'rb') as fp:photo_base64 = base64.b64encode(fp.read())photo_base64 = photo_base64.decode('utf8')return photo_base64def aiseg_request(self, url, data, headers):resp = requests.post(url=url, data=data, headers=headers, timeout=self.timeout)res = {"status_code": resp.status_code}try:res["data"] = json.loads(resp.text)return resexcept Exception as e:print(e)def make_idphoto(self, file_path, bk, spec="2"):"""证件照制作接口:param file_path::param bk::param spec::return:"""photo_base64 = self.get_photo_base64(file_path)body_json = {"photo": photo_base64,"bk": bk,"with_photo_key": 1,"spec": spec,"type": "jpg"}body = json.dumps(body_json)body_md5 = self.get_md5_data(body=body)self.headers.update({'Content-MD5': body_md5})data = self.aiseg_request(url=self.make_idphoto_url, data=body, headers=self.headers)return dataif __name__ == "__main__":file_path = "图片地址"idphoto = Idphoto(appcode="你的appcode")d = idphoto.make_idphoto(file_path, "red", "2")print(d) 3.3 实验结果与分析 原图片 背景为红色生成的证件照 背景为蓝色生成的证件照 另外尝试了使用柴犬照片做实验,也生成了证件照 原图 背景为红色生成的证件照 参考(可供参考的链接和引用文献) 1.参考:BiHand: Recovering Hand Mesh with Multi-stage Bisected Hourglass Networks(BMVC2020) 论文链接:https://arxiv.org/pdf/2008.05079.pdf 本篇文章为转载内容。原文链接:https://blog.csdn.net/m0_37758063/article/details/131128967。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-07-11 23:36:51
131
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 文章目录 一.DOM简介 1.什么是DOM 2.DOM 树 二.获取元素的方法 1.根据ID获取 2.根据标签名获取 3.通过 HTML5 新增的方法获取(注意兼容) 4.获取特殊元素(body,html) 三.事件基础 1.事件概述 2.执行事件的步骤 3.常见的鼠标事件 四.操作元素 1.操作元素内容(改变元素内容) 2. 操作常见元素属性 3.操作表单元素属性 4.操作元素样式属性 5.自定义属性的操作 6.H5自定义属性 五.节点操作 1.为什么要学习节点操作 2.节点概述 3.节点层级 一.DOM简介 1.什么是DOM 文档对象模型(简称DOM) 是W3C组织推荐的处理可扩展标记语言的标准编程接口 W3C已经定义来一系列DOM接口,通过这些DOM接口可以改变网页的内容、结构样式。 2.DOM 树 文档:一个页面就是一个文档,DOM 中使用 document 表示 元素:页面中的所有标签都是元素,DOM 中使用 element 表示 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示 文档树(Dom树):以html为根节点,形成的一颗倒立的树状结构,我们成为DOM树;这个树上所有的东西都叫节点,节点有很多类,比如文本节点,元素节点等等,这些节点如果我们通过DOM方法去获取或者其他的操作去使用就叫做DOM对象,所有节点都是DOM对象 二.获取元素的方法 1.获取页面中的元素可以使用以下几种方式 根据ID获取 根据标签名获取 通过HTML5新增的方法获取 特殊元素获取 1.根据ID获取 使用getElementByld()方法可以获取带有ID的元素对象 getElementByld(),是document下的一个方法 代码演示 <body><div id="time">2020-11-26</div><script>// 1.因为我们文档页面从上往下加载,所以先得有标签 所以我们的script写在标签下面// 2. document文档 get 获得 element 元素 by 通过 驼峰命名法// 3.参数 id是大小写敏感的字符串// 4.返回的是一个对象var timer = document.getElementById('time');console.log(timer);// 5.console.dir 打印我们返回得的元素对象 更好的查看里面的属性和方法console.dir(timer);</script></body> 2.根据标签名获取 使用getElementsByTagName()方法可以返回带有指定标签名的对象的集合 语法如下 document.getElementsByTagName('标签名') 注意: 1.因为得到的是一个对象的集合,使用我们想要操作里面的元素就需要遍历 得到元素对象是动态的 代码演示 <body><ul><li>我们的征程是星辰大海</li><li>我们的征程是星辰大海</li><li>我们的征程是星辰大海</li><li>我们的征程是星辰大海</li><li>我们的征程是星辰大海</li></ul><ul id="nav"><li>心存感恩,所遇皆美好~</li><li>心存感恩,所遇皆美好~</li><li>心存感恩,所遇皆美好~</li><li>心存感恩,所遇皆美好~</li><li>心存感恩,所遇皆美好~</li></ul><script>// 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储的var lis = document.getElementsByTagName('li')console.log(lis);// 2.如果想要依次打印里面的元素对象我们可以采取遍历方式for (var i = 0; i < lis.length; i++) {console.log(lis[i]);}// 3.这里可以是可以获取标签的.getElementsByTagName()可以得到这个元素里面的某些标签var nav1 = document.getElementById('nav') //这个获取nav元素var navli = nav.getElementsByTagName('li') //这里是获取nav 里面的li标签 要先获取 nav元素在获取里面的liconsole.log(navli);</script></body> 3.通过 HTML5 新增的方法获取(注意兼容) 1. document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合 2. document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象 3. document.querySelectorAll('选择器'); // 根据指定选择器返回所有元素对象集合 注意:querySelector 和 querySelectorAll里面的选择器需要加符号,比如:document.querySelector(’nav’); 代码演示 <body><div class="box">盒子1</div><div class="box">盒子2</div><div id="nav"><ul><li>首页</li><li>产品</li></ul></div><script>// 1. getElementsByClassName 根据类名获得某些元素集合var boxs = document.getElementsByClassName('box');console.log(boxs);// 2. querySelector 返回指定选择器的第一个元素对象 切记 里面的选择器需要加符号 .box navvar firstBox = document.querySelector('.box');console.log(firstBox);var nav = document.querySelector('nav');console.log(nav);var li = document.querySelector('li');console.log(li);// 3. querySelectorAll()返回指定选择器的所有元素对象集合var allBox = document.querySelectorAll('.box');console.log(allBox);var lis = document.querySelectorAll('li');console.log(lis);</script> 4.获取特殊元素(body,html) 获取body元素 - doucumnet.body // 返回body元素对象 获取html元素 . document.documentElement // 返回html元素对象 代码演示 <body><script>// 获取bdoy元素var bodyEle = document.bodyconsole.log(bodyEle); //返回body元素// 获取html元素var htmlEle = document.documentElementconsole.log(htmlEle); //返回html元素</script></body> 三.事件基础 1.事件概述 JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。 简单理解: 触发— 响应机制。 网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个 事件,然后去执行某些操作。 代码演示 <body><button id="btn">浩哥</button><script>// 点击一个按钮,弹出一个对话框// 1.事件是有三部分组成的 1.事件源 2.事件类型 3.事件处理程序 也称为事件三要素// (1).事件源 事件被触发的对象 var but = document.getElementById('btn')// (2).事件类型 如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过还是????// (3).事件处理程序 通过一个函数赋值的方式 完成 因为函数就是实现某种功能的but.onclick = function() {alert('浩哥爱编程')}</script></body> 2.执行事件的步骤 1. 获取事件源DOM对象(意思是你要获取那个元素) 2. 注册事件(绑定事件 意思是通过什么方式来处理比如是鼠标经过还是鼠标点击等等行为) 3. 添加事件处理程序(采取函数赋值形式 意思是你想做啥) 代码演示 <body><div>123</div><script>// 事件执行步骤 点击div 控制台输出我被选中了// 1.获取事件源var div = document.querySelector('div')// 2.绑定事件 注册事件// div.onclick// 3.添加事件处理程序div.onclick = function() {console.log('我被点击了');}</script></body> 3.常见的鼠标事件 onmouseenter鼠标移入事件 onmouseleave鼠标移出事件 四.操作元素 JS的DOM操作可以改变网页内容、结构和样式,利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性 1.操作元素内容(改变元素内容) elemeny.innerText 从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉 elemernt.innerHTML 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行 elemernt.Content可以获取隐藏元素的文本,包含换行和空白 代码演示 <title>Document</title><style>div,p {height: 30px;width: 300px;line-height: 30px;text-align: center;color: fff;background-color: pink;}</style></head><body><button>显示当前系统时间</button><div>某个时间</div><p>123</p><script>// 当我们点击了按钮,div里面的文字会发生变化// 1.获取元素 注意这里的按钮 和div都要获取到 因为 点击按钮div里面要发生变化所以都要获取var but = document.querySelector('button');var div = document.querySelector('div');// 2.绑定事件// but.onclick// 3.程序处理but.onclick = function() {// 改变元素内容 element(元素).innerTextdiv.innerText = '2020-11-27'}// 4.我们元素可以不用添加事件,就可以直接显示日期var p = document.querySelector('p');p.innerText = '2020-11-27';</script> elemeny.innerText和elemeny.innerHTML的区别 代码演示 <body><div></div><p></p><ul><li> 文字</li><li>123</li></ul><script>// innertText 和 innertHTML 的区别// 1. innerText 不识别html标签 非标准 去除空格和换行var div = document.querySelector('div');div.innerText = '<strong>今天是:</strong> 2020';// 2.innertHTML 识别html标签 W3C标准 保留空格和换行的 推荐尽量使用这个 因为这个是标准var p = document.querySelector('p')p.innerHTML = '<strong>今天是:</strong> 2020';// 3.这俩个属性是可读写的 意思是 除了改变内容还可以元素读取里面的内容的var ul = document.querySelector('ul')console.log(ul.innerText);console.log(ul.innerHTML);// .4innerHtml innerText 之间的区别:设置内容的时候,如果内容当中包含标签字符串 innerHtml会有标签的特性,也就是说标签会在页面上生效如果内容当中包含标签字符串 innerText会把标签原样展示在页面上,不会让标签生效读取内容的时候,如果标签内部还有其它标签,innerHtml会把标签内部带着其它的标签全部输出如果标签内部还有其它标签,innerText只会输出所有标签里面的内容或者文本,不会输出标签如果标签内部没有其它标签,他们两个一致;都是读取文本内容,innerHtml会带空白和换行</script></body> 2. 操作常见元素属性 innerText、innerHTML 改变元素内容 src、href id、alt、title 代码演示 <body><button id="ldh">刘德华</button><button id="zxy">张学友</button><br><img src="./images/ldh.jpg" alt="" width="200px" height="200px" title="刘德华" id="img"><script>// 修改属性 src// 我们可以操作元素得方法 来修改元素得属性 就是 元素的是什么属性 在重新给值就可以完成相应的赋值操作了// 1.获取元素var ldh = document.getElementById('ldh')var zxy = document.getElementById('zxy')var img = document.getElementById('img')// 2.注册事件 程序处理zxy.onclick = function() {// 当我们点击了图片的时候图片路径就发生变化 这里的.表示 的 得意思 img对象下的src属性img.src = './images/zxy.jpg';// 当我们变换图片得同时里面得title也要跟着变 所以前面要加上img.img.title = '张学友';}ldh.onclick = function() {img.src = './images/ldh.jpg';img.title = '刘德华';}</script> 3.操作表单元素属性 利用DOM可以操作如下表单元素的属性 type、value、checked、selected、disabled 代码演示: <body><button>按钮</button><input type="text" value="输入内容"><script>// 我想把value里面的输入内容改变为 被点击了// 1.获取元素var but = document.querySelector('button')var input = document.querySelector('input')// 2.注册事件 处理程序but.onclick = function() {// input.innerHTML = '被点击了'; 这个是 普通盒子 比如 div 标签里面的内容// 表单里面的值 文字内容是通过value来修改的input.value = '被点击了'// 如果需要某个表单被禁用 不能再点击了使用 disabled 我们想要这个按钮 button禁用// but.disabled = true// 还有一种写法// this指向的是事件函数的调用者 谁调用就指向谁 这里调用者是btnthis.disabled = true}</script></body> 4.操作元素样式属性 我们可以通过 JS 修改元素的大小、颜色、位置等样式。 1.element.style 行内样式操作 注意: JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor JS 修改 style 样式操作,产生的是行内样式,所以行内式比内嵌式高 代码演示 <style>div {width: 200px;height: 200px;background-color: red;}</style></head><body><div></div><script>// 要求点击div变成粉色 height变为250px// 1.获取元素var div = document.querySelector('div');// 2.注册事件 处理程序div.onclick = function() {// div.style里面的属性 采取的是驼峰命名法// this等于div this调用者 谁调用谁执行this.style.backgroundColor = 'pink'this.style.height = '250px'}</script> 2.element.className 类名样式操作 注意: 如果样式修改较多,可以采取操作类名方式更改元素样式。 class因为是个保留字,因此使用className来操作元素类名属性 className 会直接更改元素的类名,会覆盖原先的类名。 代码演示 <style>div {width: 100px;height: 100px;background-color: pink;}.change {background-color: purple;color: fff;font-size: 25px;margin-top: 100px;}</style></head><body><div class="first">文本</div><script>// 1. 使用 element.style 获得修改元素样式 如果样式比较少 或者 功能简单的情况下使用var test = document.querySelector('div');test.onclick = function() {// this.style.backgroundColor = 'purple';// this.style.color = 'fff';// this.style.fontSize = '25px';// this.style.marginTop = '100px';// 让我们当前元素的类名改为了 change// 2. 我们可以通过 修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况 如果想继续添加样式即在change添加即可// 3. 如果想要保留原先的类名,我们可以这么做 多类名选择器// this.className = 'change';this.className = 'first change';}</script> 5.自定义属性的操作 js给我们规定了可以自己添加属性 在操作元素属性的时候,元素.语法只能操作元素天生具有的属性,如果是自定义的属性,通过.语法是无法操作的只能通过getAttribute和setAttribute去操作,他俩是通用的方法,无论元素天生的还是自定义的都可以可以操作 1.获取属性值 element.属性 获取属性值。 element.getAttribute(‘属性’); 区别: element.属性 获取内置属性值(元素本身自带的属性 如果是自定义属性不能被获取) element.getAttribute(‘属性’);主要获得自定义的属性 (标准) 我们自定义的属性 2.设置属性值 element.属性 = ‘值’ 设置内置属性值 element.setAttribute(‘属性’,‘值’) 区别: element.属性 设置内置属性值 element.setAttribute(‘属性’);主要设置自定义的属性(标准) 3.移除属性 element.removeAttribute(‘属性’); 代码演示 <body><div id="demo" index="1" class="nav"></div><script>var div = document.querySelector('div');// 1.获取元素的属性值// (1) element.属性console.log(div.id);// (2) element.getAttribute('属性') get获取得到 attribute属性的意思 我们自己添加的属性称之为自定义属性console.log(div.getAttribute('id')); //democonsole.log(div.getAttribute('index')); // 1// 2.设置元素的属性值// (1) element.属性 = '值' div.id = 'test'div.className = 'navs'// (2) element.setAttribute('属性','值')div.setAttribute('index', 2);div.setAttribute('class', 'footer') //这里就是class 不是className 比较特殊// 3.移除属性 removeAttribute(属性)div.removeAttribute('index');</script></body> 只要是自定义属性最好都是用element.setAttribute(‘属性’,‘值’)来设置 如果是自带属性用element.属性来设置 6.H5自定义属性 自定义属性的目的:第一、是为了保存属性 第二、并且使用数据。有一些数据可以保存到页面中而不用保存到数据库中。 自定义属性获取是通过getAttribute(‘属性’) 获取的 但是有些自定义属性很容易引起歧义,不容易判断是元素还是自定义属性 H5给我们新增了自定义属性: 1.设置H5自定义属性 H5规定自定义属性data-开头做为属性名并且赋值 比如<div data-index:“1”> 或者使用JS设置element.setAttribute(‘deta-index’,2) 2.获取H5自定义属性 兼容性获取 element.getAttribute(‘data-index’) 推荐开发中使用这个 H5新增element.dataset.index 或者element.datase[‘index’] ie 11以上才支持 代码演示 <body><div getTime="10" data-index="20" data-name-list="40"></div><script>// 获取元素var div = document.querySelector('div');console.log(div.geTime); //undefined getTime是自定义属性不能直接通过元素的属性来获取 而是用自定义属性来获取的getAttribute(‘属性’)console.log(div.getAttribute('getTime')); //10// H5添加自定义属性的写法以data-开头div.setAttribute('data-time', 30)// 1.兼容性获取H5自定义属性console.log(div.getAttribute('data-time')); // 30// 2.H5新增的获取自定义属性的方法 它只能获取data-开头的// dataset 是一个集合的意思存放了所有以data开头的自定义属性 如果你想取其中的某一个只需要在dataset.的后面加上自定义属性名即可console.log(div.dataset);console.log(div.dataset.time); // 30// 还有一种方法dataset['属性']console.log(div.dataset['time']); // 30// 如果自定义属性里面有多个-链接的单词 我们获取的时候采取驼峰命名法 不用要-了console.log(div.dataset.nameList); // 40console.log(div.dataset['nameList']); // 40</script></body> 五.节点操作 1.为什么要学习节点操作 获取元素通常使用俩种方式 (1)利用DOM提供的方法获取元素 但是逻辑性不强 繁琐 (2)利用节点层级关系获取元素 如 利用父子,兄弟关系获取元素 逻辑性强,但是兼容性不怎么好 2.节点概述 网页中的所有内容都是节点(标签、属性、文本、注释等等) ,在DOM中,节点使用node表示。HTML DOM 树中的所有节点均可通过javascript进行访问,所有HTML元素(节点) 均可被修改,也可以创建或删除 一般地,节点至少拥有nade Type(节点类型)、nodeName(节点名称)和nodeValue(节点值) 这三个基本属性 元素节点 nodeType 为 1 属性节点 node Name为 2 文本节点 nodeValue为 3 (文本节点包含文字、空格、换行等等) 实际开发中,节点操作主要操作的是元素节点 3.节点层级 利用DOM树可以把节点划分为不同得层级关系,常见得是父子兄层级关系 1.父级节点 1.node.parentNode parenNode属性可以返回某节点得父节点,注意是最近的父节点哟!!! 如果指定的节点没有父节点就返回null 代码演示 <body><div class="box"><div class="box1"></div></div><script>var box1 = document.querySelector('.box1')// 得到的是离元素最近的父节点(亲爸爸) 得不到就返回得是nullconsole.log(box1.parentNode); // parentNode 翻译过来就是父亲的节点</script></body> 2.子级节点操作 1.parentNode.children(非标准) parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回(重点记住这个就好,以后重点使用) 虽然children是一个非标准,但是得到了各个浏览器的支持,我们大胆使用即可!!! 代码演示 <body><ul><li>1</li><li>1</li><li>1</li><li>1</li></ul><script>// DOM 提供的方法(APL)获取 这样获取比较麻烦var ul = document.querySelector('ul')var lis = ul.querySelectorAll('li')// children子节点获取 ul里面所有的小li 放心使用没有限制兼容性 实际开发中经常使用的console.log(ul.children);</script> 如何返回子节点的第一个和最后一个? 2.parentNode.firstElementChild firstElementChild返回第一个子元素节点,找不到则返回unll 3.parentNode.lastElementChild lastElementChild返回最后一个子元素节点,找不到则返回null 注意:这俩个方法有兼容性问题,IE9以上才支持 谨慎使用 但是我们有解决方案 如果想要第一个子元素节点,可以使用 parentNode.chilren[0] 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1] 代码演示 <body><ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><script>var ul = document.querySelector('ul')// 1.firstElementChild 返回第一个子元素节点 ie9 以上才支持注意兼容console.log(ul.firstElementChild);// 2.lastElementChild返回最后一个子元素节点console.log(ul.lastElementChild);// 3.实际开发中用到的既没有兼容性问题又可以返回子节点的第一个和最后一个console.log(ul.children[0]);console.log(ul.children[ul.children.length - 1]); //ul.children.length - 1获取的永远是子节点最后一个</script></body> 3.兄弟节点 1.node.nextSibling nextSibling 返回当前元素的下一个兄弟节点,找不到则返回null。注意包含所有的节点 2.node.previousSibling previousSibling 返回当前元素上一个兄弟节点,找不到则返回null。注意包含所以有的节点 代码演示 <body><div>我是div</div><span>我是span</span><script>var div = document.querySelector('div')// 返回当前元素的下一个兄弟节点nextSibling,找不到返回null。注意包含元素节点或者文本节点等等console.log(div.nextSibling); //这里返回的是text 因为它的下一个兄弟节点是换行// 返回的是当前元素的上一个节点previousSibling,找不到返回null。注意包含元素节点或者文本节点等等console.log(div.previousSibling); //这里返回的是text 因为它的上一个兄弟节点是换行</script></body> 3.node.nexElementSibling nexElementSibling 返回当前元素下一个兄弟元素节点,找不到返回null 4.node.previousElementSibling previousElementSibling返回当前元素上一个兄弟节点,找不到返回null 注意:这俩个方法有兼容性问题,IE9以上才支持 代码演示 <body><div>我是div</div><span>我是span</span><script>var div = document.querySelector('div')// nextElementSiblingd得到下一个兄弟元素节点console.log(div.nextElementSibling); // span // previousElementSibling 得到的是上一个兄弟元素节点console.log(div.previousElementSibling); // null 因为它上面没有兄弟元素了返回空的</script></body> 怎么解决兼容性问题呢? 可以封装一个兼容性函数(简单了解即可 在实际开发中用的不多) function getNextElementSibling(element) {var el = element;while (el = el.nextSibling) {if (el.nodeType === 1) {return el;} }return null;} 4.创建节点 1.document.createElement('tagName') document.createElement( ) 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在的是根据我们的需求动态生成的,所有我们也称为动态创建元素节点 我们创建了节点要给添加到节点里面去 称为 添加节点 1.node.appendChild(child) node.appendChild( )方法将一个节点添加到指定父节点的子节点列表末尾 2.node.insertBefore(child,指定添加元素位置) node.insertBefore( ) 方法将一个节点添加到父节点的指定子节点前面 代码演示 <body><ul><li>1</li></ul><script>// 1.创建节点 createElementvar li = document.createElement('li')// 2.添加节点 创建了节点要添加到某一个元素身上去 叫添加节点 node.appendChild(child) done 父级 child 子级 如果前面有元素了则在后面追加元素类似数组中的push依次追加var ul = document.querySelector('ul')ul.appendChild(li)// 3.添加节点 node.insertBefore(child,指定元素) 在子节点前面添加子节点 child子级你要添加的元素var lili = document.createElement('li')ul.insertBefore(lili, ul.children[0]) //ul.children 这句话的意思是添加到ul父亲的子节点第一个// 总结 如果想在页面中添加元素分为俩步骤1.创建元素 2.添加元素</script></body> 5.删除节点 node.removeChild(child) node.removeChlid()方法从DOM 中删除一个子节点,返回删除的节点 简单点就是从父元素中删除某一个孩子node就是父亲child就是孩子 删除的节点.remove(没有参数) 注意:ie不支持 代码演示 <body><button>按钮</button><ul><li>熊大</li><li>熊二</li><li>熊三</li></ul><script>// 1.获取元素var ul = document.querySelector('ul')var but = document.querySelector('button');// 2.删除元素// but.onclick = function() {// ul.removeChild(ul.children[0])// }// 3.点击按钮键依次删除,最后没有删除内容了 就禁用按钮 disabled = true 禁用按钮语法but.onclick = function() {if (ul.children.length == 0) {this.disabled = true} else {ul.removeChild(ul.children[0])} }</script></body> 6.复制节点(克隆节点) node.cloneNode() node.dloneNode()方法返回调用该方法节点得一个副本,也称为克隆节点/拷贝节点 注意 1.如果括号参数为空或者为false,则是浅拷贝,只复制里面得标签,不复制内容 2.如果括号参数为true,则是深度拷贝,会复制节点本身以及里面所有的内容 代码演示 <body><ul><li>1</li><li>2</li><li>3</li></ul><script>// 1.获取元素var ul = document.querySelector('ul');// 2.复制元素 node.cloneNode() 如果参数括号为空或者false则只会复制元素不会复制内容,如果待有参数true则内容和元素都会被复制var lis = ul.children[0].cloneNode(true);// 3.获取元素ul.appendChild(lis)</script></body> 7.替换(改)节点 node.replaceChild(新节点,替换到什么位置) 代码演示 <body><ul class="list"><li>1</li><li>2</li></ul><script>// 替换(改)节点 父节点.replaceChild(新元素, 替换到什么位置)// (1)获取父元素var ulNode = document.querySelector('.list');// (2)创建新的元素var liRead = document.createElement('li')// (3)给新元素添加内容liRead.innerHTML = '5';// (4)替换元素ulNode.replaceChild(liRead, ulNode.children[1])</script></body> 8.三种动态创建元素区别 document.write() element.innerHTML document.createElement() 区别 document.write()是直接将内容写入页面的内容流,但是文档流执行完毕,它则会导致页面全部重绘 element.innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘 element.innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结果有点复杂 createElement()创建多个元素效率低一点点,但是结果更加清晰 总结:不同浏览器下,innerHTML效率要比createElement()高 代码演示 <body><button>点击</button><p>abc</p><div class="inner"></div><div class="create"></div><script>// window.onload = function() {// document.write('<div>123</div>');// }// 三种创建元素方式区别 // 1. document.write() 创建元素 如果页面文档流加载完毕,再调用这句话会导致页面重绘// var btn = document.querySelector('button');// btn.onclick = function() {// document.write('<div>123</div>');// }// 2. innerHTML 创建元素var inner = document.querySelector('.inner');// for (var i = 0; i <= 100; i++) {// inner.innerHTML += '<a href="">百度</a>'// }var arr = [];for (var i = 0; i <= 100; i++) {arr.push('<a href="">百度</a>');}inner.innerHTML = arr.join('');// 3. document.createElement() 创建元素var create = document.querySelector('.create');for (var i = 0; i <= 100; i++) {var a = document.createElement('a');create.appendChild(a);}</script></body> 本篇文章为转载内容。原文链接:https://blog.csdn.net/m0_46978034/article/details/110190352。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-08-04 13:36:05
247
转载
转载文章
...,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。 本文为课程《激光原理》课程调研综述论文成果,要求为调研激光相关的某个领域,并写5000字小综述一篇。论文完成时间:2021-11。 版权声明:除特殊标注外,本文全部图片及文字版权归作者所有,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/yyyyang666/article/details/129210164 激光诱导击穿光谱联合激光诱导荧光技术(LIBS-LIF)在环境监测上的元素分析应用 摘 要: 环境监测的重要性在当今环境问题日渐突出的背景下愈发显著。在环境问题中,土壤问题和水质问题是十分重要的课题之一,对于土壤监测和水质监测往往使用元素分析的方法。传统的实验室检测方式虽然精度高、准确性好,但是耗时长、流程复杂,无法实现原位检测或远程快速检测。使用激光诱导击穿光谱(LIBS)可以有效改善上述问题,但是其准确率低,存在相邻特征谱线干扰。激光诱导击穿光谱联合激光诱导荧光技术(LIBS-LIF)则是对LIBS技术的进一步强化升级,满足了检测需求。文章首先介绍了LIBS技术以及LIBS-LIF技术的基本原理;接着简要介绍LIBS-LIF技术在土壤监测的应用情况,介绍了技术的应用起源和研究进展;然后介绍LIBS技术和LIBS-LIF技术在水质监测方面的应用,由于液体检测中对于预处理的方式最为重要,因此此处简要归纳了液体检测样品预处理的方法,最后对LIBS-LIF技术在环境方面的应用做出总结和展望。LIBS-LIF技术具有着传统实验室检测无法比拟的优势,也正处于热门研究方向,未来潜力无限。 关键词: 激光诱导击穿光谱(LIBS);激光诱导击穿光谱联合激光诱导荧光技术(LIBS-LIF);环境监测;土壤监测;水质监测 Elemental Analysis Application of Laser Induced Breakdown Spectroscopy assisted with Laser Induced fluorescence(LIBS-LIF) Technology in Environmental Monitoring Abstract: The importance of environmental monitoring is becoming more and more significant under the background of increasingly prominent environmental problems. Among the environmental problems, soil problem and water quality problem is one of the very important topics. Element analysis is often used for soil monitoring and water quality monitoring. Although the traditional laboratory detection method has high accuracy and good accuracy, it takes a long time and the process is complex, so it is impossible to realize in-situ detection or remote rapid detection. Laser induced breakdown spectroscopy (LIBS) can effectively improve the above problems, but its accuracy is low and there is interference between adjacent characteristic lines. Laser-induced breakdown spectroscopy assisted with laser-induced fluorescence (LIBS-LIF) is a further enhancement and upgrade of LIBS technology to meet the detection needs. This paper first introduces the basic principles of LIBS technology and LIBS-LIF technology, then briefly introduces the application of LIBS-LIF technology in soil monitoring, and introduces the application origin and research progress of LIBS-LIF technology. Then it introduces the application of LIBS technology and LIBS-LIF technology in water quality monitoring. Because the way of pretreatment is the most important in liquid detection, the pretreatment methods of liquid testing samples are briefly summarized here. Finally, the application of LIBS-LIF technology in the environment is summarized and prospected. LIBS-LIF technology has incomparable advantages over traditional laboratory testing, and it is also in a hot research direction, with unlimited potential in the future. Keywords: Laser induced breakdown spectroscopy(LIBS); Laser induced breakdown spectroscopy assisted with Laser Induced fluorescence(LIBS-LIF); Environmental monitoring; Soil monitoring; Water quality monitoring Completion time: 2021-11 目录 0. 引言 1. 技术简介 1.1 LIBS技术简介 1.1.1 LIBS技术的基本原理 1.1.2 LIBS技术的定量分析 1.1.3 LIBS技术的优缺点 1.2 LIBS-LIF技术 1.2.1 LIF技术的基本原理 1.2.2 Co原子的LIBS-LIF增强原理 2. LIBS-LIF技术用于土壤监测 2.1 早期研究 2.2 近期研究现状 3. LIBS及LIBS-LIF技术用于水质监测 3.1液体直接检测 3.2液固转换检测 3.2.1吸附法 3.2.2成膜法 3.2.3微萃取法 3.2.4冷冻法 3.2.5电沉积法 3.3液气转换检测 4. 总结与展望 参考文献 0. 引言 随着经济的发展,人们物质生活水平提高的同时,环境的问题也愈发突出,其中,土壤问题和水体问题十分突出。 土壤是包括人类在内的一切生物体生存的载体,土壤的质量与农作物的生长息息相关,而农作物的收成则是人类发展的基石。在工业化发展的影响下,土壤重金属污染和积累成为了一个世界性的问题,尤其在中国特别是长三角地区尤为严重[1]。 水是生命之源,水体问题直接关系到所有生物体的生存。环境中的水体问题,主要集中在工业废水的治理与监测上。工业废水中含有大量重金属元素,其难以生物降解,重金属元素会随着水体流动而扩散。 物质元素分析在土壤分析和水质分析上是常用的方式。传统的分析方法是基于实验室的元素光谱分析法,其具有高精度、高稳定的特点,如:原子吸收光谱法(Atomic absorption spectrometry, AAS)、电感耦合等离子体质谱法(Inductively coupled plasma mass spectrometry, ICP-MS)、电感耦合等离子体原子发射光谱法(Inductively coupled plasma atomic emission spectrometry, ICP-AES)等,但是此类光谱的检测样品预处理复杂、检测操作难度高、需要庞大复杂的实验设备,且对样品造成损坏,有所不便[2,3]。 激光诱导击穿光谱(Laser induced breakdown spectroscopy,LIBS)是一种基于原子光谱分析技术,与传统的光谱分析技术相比,其实验装置简单便携、操作简便、应用广泛、可远程测量,同时有在简单预处理样品或根本不预处理的情况下进行现场测量的潜力。因此,其满足在环境监测中,特别是土壤监测和水质监测此类希望可以在现场检测、快速便捷检测,同时精度较高的需求。LIBS技术很容易与其他技术如激光诱导荧光技术(Laser induced fluorescence, LIF)、拉曼光谱(Raman)等技术联用,进一步提高了 LIBS技术的检测准确度和竞争力[4]。 1. 技术简介 1.1 LIBS技术简介 LIBS技术最早可以追溯到20世纪60年代Brech, F.和Cross, L.所做的激光诱导火花散射实验,其中的一项实验使用红宝石激光器产生的激光照射材料后产生等离子体羽流。经过了几十年的发展,LIBS技术得到了显著发展,其在环境检测、文物保护鉴定、岩石检测、宇宙探索等领域中被广泛应用。 1.1.1 LIBS技术的基本原理 LIBS技术的装置主要由脉冲激光器、光谱仪、样品装载平台和计算机组成,光谱仪和计算机之间常常由光电倍增管或CCD等光电转换器件连接,如图 1所示[3]。 图 1 LIBS实验装置图[3] 首先,通过脉冲激光器产生强脉冲激光后由透镜聚焦到样品上,被聚焦区域的样品吸收,产生初始自由电子,并在持续的激光脉冲作用下加速。初始自由电子获取到足够高的能量之后,会轰击原子电离产生新的自由电子。随着激光脉冲作用的持续,自由电子和原子的作用如此往复碰撞,在短时间内形成等离子体,形成烧蚀坑。接着,激光脉冲结束,等离子体温度逐渐降低,产生连续背景辐射并产生原子或离子的发射光谱。通过光谱仪采集信号,在计算机上分析特征谱线的波长和强度信息就可以对样本中的元素进行定性和定量分析[2]。 1.1.2 LIBS技术的定量分析 由文献[2]可知,LIBS技术的定量分析方法通常有外标法、内标法和自由校准法(CF)。其中,最简单方便的是外标法。 外标法由光谱分析基本定量公式Lomakin-Scheibe公式 I=aCb(1)I=aC^b \tag{1} I=aCb(1) 式中III为光谱强度,aaa为比例系数,CCC为元素浓度,bbb为自吸收系数。自吸收系数bbb会随着元素浓度CCC的减小而增大,当元素浓度CCC很小时,b=1b=1b=1。使用同组仪器测量时aaa和bbb的值为定值。 将式(1)左右两边取对数,得 lgI=blgC+lga(2)lgI=blgC+lga \tag{2} lgI=blgC+lga(2) 由式(2)可知,当b=1时,光谱强度和元素浓度呈线性关系。因此,可以通过检验一组标准样品的元素浓度和对应的光谱强度,绘制出对应的标准曲线,从而根据曲线的得到未知样品的浓度值。 如图 2 (a)(b)所示,通过使用LIBS技术多次测定一系列含有Co元素的标准样品的光谱强度后取平均可以绘制出图 2 (b)所示的校正曲线[5]。同时可以计算出曲线的相关系数R^2、交叉验证均方差(RMSECV)和样品中Co元素的检出限(LOD)。 图 2 用LIBS和LIBS-LIF技术测定有效钴元素的光谱和校准曲线[5] (a) (b)使用LIBS技术测定,(c) (d)使用LIBS-LIF技术测定 1.1.3 LIBS技术的优缺点 随着LIBS技术的提高和广泛应用,其自身独特的优势也显示出来,其主要优点主要如下[6]: (1)样品不需要进行预处理或只需要稍微预处理。 (2)样品检测时间短,相较于传统的AAS、ICP-AES等技术检测需要几分钟到几小时的时间相比,LIBS技术检测只需要3-60秒。 (3)样品的检出限LOD高,对于低浓度样品检测更加灵敏精确。 (4)实验装置结构简单,便携性高。 (5)可用于远程遥感监测 (6)对于检测样品的损伤基本没有,十分适合对于文物遗迹等方面进行应用 LIBS技术也有着自身的缺陷,其中问题最大的就是相较于传统的AAS、ICP-AES等技术来说,LIBS的检测准确性低,只有5-20%。 但LIBS还有一个优点在于很容易与其他技术如激光诱导荧光技术(Laser induced fluorescence, LIF)、拉曼光谱(Raman)等技术联用,可以弥补LIBS技术的检测准确率低的缺陷,同时结合其他技术的优势提高竞争力[7]。 1.2 LIBS-LIF技术 LIBS技术常常与LIF技术联合使用,即LIBS-LIF技术。通过LIF技术对特征曲线信号的选择性加强作用,有效的提高了检测的准确率,改善了单独使用LIBS检测准确率低的缺陷。 LIBS-LIF技术在1979年由Measures, R. M.和Kwong, H. S.首次使用,用于各种样品中微量铬元素的选择性激发。 1.2.1 LIF技术的基本原理 LIF技术,是通过激光辐射激发原子或者分子,之后被照射的原子或分子自发发射出的荧光。 首先,调节入射激光的波长,从而改变入射激光的能量。之后,当入射激光的能量与检测区域中的气态分子或原子的能级差相同时,分子或原子将被激光共振激发跃迁至激发态,但是这种激发态并不稳定,会通过自发辐射释放出另一个光子能量并向下跃迁,同时发射出分子或原子荧光,这便是激光诱导荧光。 其中,分子或原子发射荧光的跃迁过程主要有共振荧光、直越线荧光、阶跃线荧光和多光子荧光四种,如图3所示[2]。元素被激发的直跃线荧光往往强度大,散射光干扰弱,故被常用。 图 3 分子或原子发射荧光的跃迁过程[2] 1.2.2 Co原子的LIBS-LIF增强原理 下面将以Co元素为例,说明LIBS-LIF技术的原理。 Co元素直跃线荧光的产生原理图如图 4所示[5]。波长为304.40nm的激光能量刚好等于Co原子基态到高能态(4.07eV)的能级差,Co原子被304.40nm的激发照射后跃迁至该能级。随后,该能级上的Co原子通过自发辐射释放能量跃迁至低能态(0.43eV),同时发出波长为304.51nm的荧光。因此,采用LIF的激发波长为304.40nm,光谱仪对应的检测波长为304.51nm。 图 4 Co元素直跃线荧光产生原理图[5] LIBS-LIF技术的装置如图 5所示[5],与LIBS装置不同的是其增加了一台可调激光器,如染料激光器、OPO激光器等。其用于激发特定元素的被之前LIBS激发出的等离子体。该激光平行于样品表面照射,不会对样品产生损伤。 图 5 LIBS-LIF实验装置图[5] 在本次Co元素的检测中,OPO激光器的波长为304.40nm。样品首先通过脉冲激光器垂直照射后产生等离子体,原理和LIBS技术一致。之后使用OPO激光器产生的304.40nm的激光照射等离子体,激发荧光信号,增强特征谱线的强度。最后通过光谱仪采集信号,在计算机上分析特征谱线。 LIBS-LIF技术对Co原子测定的光谱和校正曲线如图 2 (c)(d)所示。通过与(a)(b)图对可得到,使用LIBS-LIF技术明显增强了Co原子的特征谱线强度,同时定量分析得到的校正曲线的相关系数R^2、交叉验证均方差(RMSECV)和样品中Co元素的检出限(LOD)数值都有很好的改善。 2. LIBS-LIF技术用于土壤监测 土壤监测是LIBS-LIF技术的最传统应用方向之一。土壤成分复杂,蕴含多种微量元素,这些元素必须维持在合理的范围内。若如铬等相关微量元素过低,则会对作物的生长产生影响;而若铅等重金属元素过高,则表明土地受到了污染,种植出的作物可能存在重金属残留的问题。 2.1 早期研究 LIBS-LIF技术用于大气压下的土壤元素检测可以最早追溯到1997年Gornushkin等人使用LIBS技术联合大气紫外线测定石墨、土壤和钢中钴元素的可行性[8],其紫外线即起到作为LIF光源的作用。 之后,为了评估该技术在现场快速检测分析中的可行性,其使用了可以同时检测分析22种元素的Paschen-Runge光谱仪以发挥LIBS技术可以快速检测多种元素的优势。同时使用染料激光器作为LIF光源,使用LIBS-LIF技术对Cd和TI元素进行了信号选择性增强测量,排除了邻近元素谱线的干扰。但是对于Pb元素还无法检测[9]。 2.2 近期研究现状 华中科技大学GAO等人在2018年对土壤中难以检测的Sb元素使用LIBS-LIF技术进行检验,排除了检验Sb元素时邻近Si元素的干扰,并探讨了使用常规LIBS时在287nm-289nm的波长下不同的ICCD延时长度对信号强度的影响,以及使用LIBS-LIF技术时作为LIF光源的OPO激光器激光能量对Sb元素特征谱线信号强度与信噪比的影响、激光光源脉冲间延时长度对Sb元素特征谱线信号强度与信噪比的影响,由相关结果得到了最优实验条件[10],如图 6至图 8所示。 图 6 不同ICCD延迟时间下样品在287.0-289.0 nm波段的光谱 图 7 LIBS-LIF和常规LIBS得到的光谱比较 图 8 Sb特征谱线的强度和信噪比曲线 (A)Sb特征谱线的强度和信噪比随OPO激光能量的变化关系;(B)Sb特征谱线的强度和信噪比随两个激光器之间脉冲延迟的变化关系 近期,该实验室研究了利用LIBS-LIF测定土壤中的有效钴含量。该实验着重于研究检测土壤中能被植物吸收的元素,即有效元素,强化研究的实际意义;利用DPTA提取样品,增大检测浓度;使用LIBS-LIF测定有效钴含量,排除了相邻元素的干扰。 3. LIBS及LIBS-LIF技术用于水质监测 LIBS及LIBS-LIF技术用于水质检测的原理和流程土壤检测基本一致,但是面临着更多的挑战。在水样的元素定量测定中,水的溅射会干扰到光的传播和收集,从而降低采集的灵敏度;由于水中羟基(OH)的猝灭作用会使得激发的等离子体寿命较短,因此等离子体的辐射强度低,进而影响分析灵敏度[2]。同时,由于部分实验方式造成使用LIBS-LIF技术不太方便,只能使用传统LIBS技术。 因此,在使用LIBS技术进行检验时还需要做相关改进。最常见的就是进行样品的预处理,在样品制备上进行改进。 由文献[11]整理可知,样品的预处理主要可以分为液体直接检测、液固转换检测、液气转换检测三种。 3.1液体直接检测 液体直接检测主要有两种方式:将光聚焦在静态液体测量和将光聚焦在流动的液体测量两种。 最早期使用LIBS技术进行检验的就是直接将光聚焦在静态液体表面测量。但其精确度和灵敏度往往比将光聚焦在流动的液体测量低。Barreda等人比较了在静态、液体喷射态和液体流动态下硅油中的铂元素使用LIBS进行检测,最后液体喷射态和液体流动态下的LOD比静态下降低了7倍[12]。 但上述实验是在有气体保护下进行的结果。总体上看,液体直接检测并不是一个很好的选择。 图 9 液体分析的三种不同实验装置图[12] a液体喷射分析,b静态液体分析,c通道流动液体分析 3.2液固转换检测 液固转换法是检测中最常用的方法,其主要可以分为以下几类: 3.2.1吸附法 吸附法是最常用的预处理方式,利用可吸附材料吸收液体中的微量元素。常用的材料有碳平板、离子交换聚合物膜,或者滤纸、竹片等将液体转换为固体,从而进行分析。 2008年,华南理工大学Chen等人以木片作为基底吸附水溶液的方式测定了Cr、Mn、Cu、Cd、Pb五种金属元素在微量浓度下的校正曲线,其检出限比激光聚焦在页面上直接分析高出2-3个数量级[13]。之后2017年,同实验室的Kang等人以木片作为基底吸附水溶液的方式,使用LIBS-LIF技术对水中的痕量铅进行了高灵敏度测量,最后得到的铅元素的LOD为~0.32ppb,超过了传统实验室检测技术ICP-AES的检测方式,为国际领先水平[14]。 3.2.2成膜法 与吸附法相反,成膜法是将水样滴在非吸水性衬底上,如Si+SiO2衬底和多空电纺超细纤维等,然后干燥成膜,从而转化为固体进行分析。 3.2.3微萃取法 微萃取法是利用萃取剂和溶液中的微量元素化学反应来实现富集。其中,分散液液体微萃取(Dispersion liquid-liquid microextraction, DLLME)是一种简单、经济、富集倍数高、萃取效率高的方法,被广泛使用。 3.2.4冷冻法 将液体冷冻成为冰是液固转化的一种直接预处理方式,冰的消融可以防止液体飞溅和摇晃,从而改善液体分析性能。 3.2.5电沉积法 电沉积法是利用电化学反应,将液体中的样品转化为固体样品并进行预浓缩,之后用于检测。该方法可以使得灵敏度大大提高,但是实验设备也变得复杂,预处理工作量也有变大。 3.3液气转换检测 将液体转化为气溶胶可以使得样品更加稳定,从而产生更稳定的检测信号。可以使用超声波雾化器和膜干燥器等产生气溶胶,再进行常规的LIBS-LIF检测。 Aras等人使用超声波雾化器和薄膜干燥器单元产生亚微米级的气溶胶,实现了液气体转换,并在实际水样上测试了该超声雾化-LIBS系统的适用性,相关实验装置如图 10、图 11所示[15]。 图 10 用于金属气溶胶分析的LIBS实验装置图[15] M:532 nm反射镜,L:聚焦准直透镜,W:石英,P:泵浦,BD:光束转储 图 11 样品导入部分结构图[15] (A)与薄膜干燥器相连的USN颗粒发生器去溶装置(加热器和冷凝器);(B)与5个武装聚四氟乙烯等离子电池相连的薄膜干燥器。G:进气口,DU:脱溶装置,W:废料,MD:薄膜干燥机,L:激光束方向,C:样品池,M:反射镜,F.L.:聚焦透镜 4. 总结与展望 本文简要介绍了LIBS和LIBS-LIF的原理,并对LIBS-LIF在环境监测中的土壤监测和水质检测做了简要的介绍和分类。 LIBS-LIF在土壤监测的技术已经逐渐成熟,基本实现了土壤的快速检测,同时也有相关便携式设备的研究正在进行。对于水质监测方面,使用LIBS-LIF检测往往集中在液固转换法的使用上,对于气体和液体直接检测,由于部分实验装置的限制,联用LIF技术往往比较困难,只能使用传统的LIBS技术。 LIBS-LIF技术快速检测、不需要样品预处理或只需要简单处理、可以实现就地检测等优势与传统实验室检测相比有着独到的优势,虽然目前由于技术限制精度还不够高,但是在当前该领域的火热研究趋势下,相信未来该技术必定可以大放异彩,为绿色中国奉献光学领域的智慧。 参考文献 [1] Hu B, Jia X, Hu J, et al.Assessment of Heavy Metal Pollution and Health Risks in the Soil-Plant-Human System in the Yangtze River Delta, China[J].International Journal of Environmental Research and Public Health,2017, 14 (9): 1042. [2] 康娟. 基于激光剥离的物质元素高分辨高灵敏分析的新技术研究[D]. 华南理工大学,2020. [3] 马菲, 周健民, 杜昌文.激光诱导击穿原子光谱在土壤分析中的应用[J].土壤学报: 1-11. [4] Gaudiuso R, Dell'aglio M, De Pascale O, et al.Laser Induced Breakdown Spectroscopy for Elemental Analysis in Environmental, Cultural Heritage and Space Applications: A Review of Methods and Results[J].Sensors,2010, 10 (8): 7434-7468. [5] Zhou R, Liu K, Tang Z, et al.High-sensitivity determination of available cobalt in soil using laser-induced breakdown spectroscopy assisted with laser-induced fluorescence[J].Applied Optics,2021, 60 (29): 9062-9066. [6] Hussain Shah S K, Iqbal J, Ahmad P, et al.Laser induced breakdown spectroscopy methods and applications: A comprehensive review[J].Radiation Physics and Chemistry,2020, 170. [7] V S D, George S D, Kartha V B, et al.Hybrid LIBS-Raman-LIF systems for multi-modal spectroscopic applications: a topical review[J].Applied Spectroscopy Reviews,2020, 56 (6): 1-29. [8] Gornushkin I B, Kim J E, Smith B W, et al.Determination of Cobalt in Soil, Steel, and Graphite Using Excited-State Laser Fluorescence Induced in a Laser Spark[J].Applied Spectroscopy,1997, 51 (7): 1055-1059. [9] Hilbk-Kortenbruck F, Noll R, Wintjens P, et al.Analysis of heavy metals in soils using laser-induced breakdown spectrometry combined with laser-induced fluorescence[J].Spectrochimica Acta Part B-Atomic Spectroscopy,2001, 56 (6): 933-945. [10] Gao P, Yang P, Zhou R, et al.Determination of antimony in soil using laser-induced breakdown spectroscopy assisted with laser-induced fluorescence[J].Appl Opt,2018, 57 (30): 8942-8946. [11] Zhang Y, Zhang T, Li H.Application of laser-induced breakdown spectroscopy (LIBS) in environmental monitoring[J].Spectrochimica Acta Part B: Atomic Spectroscopy,2021, 181: 106218. [12] Barreda F A, Trichard F, Barbier S, et al.Fast quantitative determination of platinum in liquid samples by laser-induced breakdown spectroscopy[J].Anal Bioanal Chem,2012, 403 (9): 2601-10. [13] Chen Z, Li H, Liu M, et al.Fast and sensitive trace metal analysis in aqueous solutions by laser-induced breakdown spectroscopy using wood slice substrates[J].Spectrochimica Acta Part B: Atomic Spectroscopy,2008, 63 (1): 64-68. [14] Kang J, Li R, Wang Y, et al.Ultrasensitive detection of trace amounts of lead in water by LIBS-LIF using a wood-slice substrate as a water absorber[J].Journal of Analytical Atomic Spectrometry,2017, 32 (11): 2292-2299. [15] Aras N, Yeşiller S Ü, Ateş D A, et al.Ultrasonic nebulization-sample introduction system for quantitative analysis of liquid samples by laser-induced breakdown spectroscopy[J].Spectrochimica Acta Part B: Atomic Spectroscopy,2012, 74-75: 87-94. 本篇文章为转载内容。原文链接:https://blog.csdn.net/yyyyang666/article/details/129210164。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-08-13 12:41:47
360
转载
站内搜索
用于搜索本网站内部文章,支持栏目切换。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
nohup command &
- 使命令在后台持续运行即使退出终端。
推荐内容
推荐本栏目内的其它文章,看看还有哪些文章让你感兴趣。
2023-04-28
2023-08-09
2023-06-18
2023-04-14
2023-02-18
2023-04-17
2024-01-11
2023-10-03
2023-09-09
2023-06-13
2023-08-07
2023-03-11
历史内容
快速导航到对应月份的历史文章列表。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"