用鸿蒙开发AI应用(六)UI篇
前言
上一篇,我们在鸿蒙上写了一个HDF驱动并操作了一下LED硬件,这一篇我们来尝试一下构建一个有简单界面的App,体验一下鸿蒙的前端开发流程。
环境准备
1. 安装DevEco Studio
解压相应的压缩包(文末附下载链接),这里以win10为例,双击deveco-studio-2.0.12.201.exe
指定安装目录
设置可选快捷方式和环境变量
一路下一步即可。
同意用户协议后,就能正常启动了。
2. 更新sdk
在菜单 Setting->HarmonyOS SDK->SDK Platforms
中,选择Js
和Java
,安装新版的SDK
。
同样在SDK Tools
中,选中新版的Previewer
点击Apply
更新
新建项目
点击菜单File->New Project...
,选择智慧屏Smart Vision
,创建一个空模板应用。
填入项目名称MyUiAPP
,点击完成就能创建一个工程了。
遇到 gradle
下载太慢或版本差异的,可以直接在以下网址用工具下载
https://services.gradle.org/distributions/
目录结构
我们先分析一下目录结构,做Android
开发的会倍感亲切。
1. APP
HarmonyOS
的应用软件包以APP Pack(Application Package)
形式发布,它是由一个或多个HAP(HarmonyOS Ability Package)
以及描述每个HAP
属性的pack.info
组成。HAP
是Ability
的部署包,HarmonyOS
应用代码围绕Ability
组件展开。
一个HAP
是由代码、资源、第三方库及应用配置文件组成的模块包,可分为entry
和feature
两种模块类型。
「entry」:应用的主模块。一个APP中,对于同一设备类型必须有且只有一个
entry
类型的HAP
,可独立安装运行。「feature」:应用的动态特性模块。一个
APP
可以包含一个或多个feature
类型的HAP
,也可以不含。只有包含Ability
的HAP
才能够独立运行。
2. Ability
Ability是应用所具备的能力的抽象,一个应用可以包含一个或多个Ability
。Ability
分为两种类型:FA(Feature Ability)
和PA(Particle Ability)
。FA/PA
是应用的基本组成单元,能够实现特定的业务功能。FA
有UI
界面,而PA
无UI
界面。
3. 资源文件
应用的资源文件(字符串、图片、音频等)统一存放于resources
目录下,便于开发者使用和维护。resources
目录包括两大类目录,一类为base
目录与限定词目录,另一类为rawfile
目录。
4. 配置文件
配置文件(config.json)
是应用的Ability
信息,用于声明应用的Ability
,以及应用所需权限等信息。
应用的全局配置信息,包含应用的包名、生产厂商、版本号等基本信息。
应用在具体设备上的配置信息,包含应用的备份恢复、网络安全等能力。
HAP
包的配置信息,包含每个Ability
必须定义的基本属性(如包名、类名、类型以及Ability
提供的能力),以及应用访问系统或其他应用受保护部分所需的权限等。
5. JS UI 框架
JS UI
框架是一种跨设备的高性能UI
开发框架,支持声明式编程和跨设备多态UI
。
声明式编程
JS UI
框架采用类HTML
和CSS
声明式编程语言作为页面布局和页面样式的开发语言,页面业务逻辑则支持ECMAScript
规范的JavaScript
语言。JS UI
框架提供的声明式编程,可以让开发者避免编写UI
状态切换的代码,视图配置信息更加直观。跨设备
开发框架架构上支持
UI
跨设备显示能力,运行时自动映射到不同设备类型,开发者无感知,降低开发者多设备适配成本。高性能
开发框架包含了许多核心的控件,如列表、图片和各类容器组件等,针对声明式语法进行了渲染流程的优化。
JS UI
框架包括应用层(Application)
、前端框架层(Framework)
、引擎层(Engine)
和平台适配层(Porting Layer)
。
空气质量监测 UI
1. 创建首页面
空气质量监测App包含两个界面(Page)
,工程创建完成后会生成一个名为index
的Page
,可以作为首页。
2. 创建详情页
在pages
目录按右键,弹出的菜单中选择New->JS Page
。
输入页面名称detail
,
详情页创建完成后应用工程目录如下图所示,每个Page
包括三个文件:布局文件hml
、样式文件css
、业务逻辑代码js
。
3. 开发首页
应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。
3.1 创建根节点
修改entry/src/main/js/default/pages/index/index.hml
,加入根节点div
:
<div class="container">
</div>
3.2 创建样式
修改entry/src/main/js/default/pages/index/index.css
.container { flex-direction: column;height: 480px;width: 960px;
}
3.3 添加标题栏
标题栏包括一个退出按钮和一个标题,两个控件是横向排列
<div class="container"> <div class="header" onclick="exitApp"> <image class="back" src="common/ic_back.png"></image> <text class="title"> 空气质量 </text> </div>
</div>
注意,这里要先导入common/ic_back.png
图标资源。
3.4 添加标题栏样式
修改entry/src/main/js/default/pages/detail/detail.css
,添加以下代码,设置组件的高度、边距、颜色等属性。
.header { width: 960px;height: 72px;
}
.back { width: 36px;height: 36px;margin-left: 39px;margin-top: 23px;
}
.title { width: 296px;height: 40px;margin-top: 20px;margin-left: 21px;color: #e6e6e6;
}
3.5 添加退出事件
onclick="exitApp"
设置了div
组件的click
事件,当在标题栏上触发点击事件时,就会执行函数exitApp
,该函数位于index.js
文件中,代码如下:
exitApp() { console.log('start exit'); app.terminate(); console.log('end exit');
}
app.terminate()
函数实现了程序退出功能;在使用该函数前,需要引入app
模块,在index.js
文件的最上方写如下代码:
import app from '@system.app'
在 Previewer 窗口中,可以预览界面效果
3.6 滑动组件
实现城市空气质量信息的多屏左右滑动,需要使用“swiper”
组件。
在根节点中添加一个子节点swiper
, 修改index.hml
<swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange"></swiper>
添加样式,修改index.css
.swiper {height: 385px;width: 960px;
}
绑定swiperPage
变量,swiperChange
事件,修改index.js
//引入router模块,用户页面跳转
import router from'@system.router'
import app from '@system.app'export default {//定义参数data: {//默认是第一页swiperPage: 0 },onInit () {},exitApp(){ console.log('start exit'); app.terminate(); console.log('end exit');},//swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中swiperChange (e) {this.swiperPage = e.index;}
}
在swiper
中添加两个子组件stack
(绝对布局),每个stack
组件内分别添加text、image、progress
等组件来显示对应的信息。
<div class="container"><div class="header" onclick="exitApp"><image class="back" src="common/ic_back.png"></image><text class="title">空气质量</text></div><swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange"><!--第一屏--><stack class="swiper"><!--空气质量--><text class="airquality" style="color:{{textColor1}};">{{airData[0].airQuality}}</text><!--城市名称--><text class="location-text">{{airData[0].location}}</text><!--进度条--><progressclass="circleProgress"style="color:{{textColor1}};background-Color:{{bgColor1}};"type="arc"onclick="openDetail"percent="{{percent1}}"></progress><!--云朵图片--><image class="image" src="{{src1}}"></image><!--AQI数值--><text class="pm25-value">{{ airData[0].detailData }}</text><text class="pm25-name">AQI</text><!--空气指标详细信息--><div class="detail"><div class="text-wrapper"><text class="gas-name">CO</text><text class="gas-value">100</text></div><div class="text-wrapper"><text class="gas-name">NO2</text><text class="gas-value">90</text></div><div class="text-wrapper"><text class="gas-name">PM10</text><text class="gas-value">120</text></div><div class="text-wrapper"><text class="gas-name">PM2.5</text><text class="gas-value">40</text></div><div class="text-wrapper"><text class="gas-name">SO2</text><text class="gas-value">150</text></div><input class="btn" type="button" onclick="openDetail" value="历史记录"></input></div><!--更新时间和网站等信息--><div class="footer"><text class="update-time">更新时间: 10:38</text><text class="info-source">信息来源: tianqi.com</text></div></stack><!--第二屏--><stack class="swiper"><text class="airquality" style="color: {{textColor2}};">{{airData[1].airQuality}}</text><text class="location-text">{{airData[1].location}}</text><progress class="circle-progress" style="color: {{textColor2}};background-Color: {{bgColor2}};" type="arc"percent="{{percent2}}"></progress><image class="image" src="{{src2}}"></image><text class="aqi-value">{{airData[1].detailData}}</text><text class="aqi">AQI</text><div class="detail"><div class="text-wrapper"><text class="gas-name">CO</text><text class="gas-value">10</text></div><div class="text-wrapper"><text class="gas-name">NO2</text><text class="gas-value">50</text></div><div class="text-wrapper"><text class="gas-name">PM10</text><text class="gas-value">60</text></div><div class="text-wrapper"><text class="gas-name">PM2.5</text><text class="gas-value">40</text></div><div class="text-wrapper"><text class="gas-name">SO2</text><text class="gas-value">150</text></div><input class="btn" type="button" onclick="openDetail" value="历史记录"></input></div><div class="footer"><text class="update-time">更新时间: 10:38</text><text class="info-source">信息来源: tianqi.com</text></div></stack></swiper>
</div>
3.7 页面位置指示器
添加页面位置指示器:由于当前swiper
不支持设置indicator
,需要开发者自己来实现该效果。在根节点中添加一个子组件div
,并设置相应样式;然后在该div
中添加两个子组件div
,设置两个div
的border-radius
,并在swiper
滑动事件中动态改变对应div
的背景色来实现该效果。
修改index.hml
,在swiper
组件后加入以下代码:
<div class="images"> <div class="circle-div" style="background-color: {{iconcheckedColor}};"></div> <div class="circle-div" style="background-color: {{iconUncheckedColor}};margin-left: 36px;"></div>
</div>
3.8 新增文字样式
修改 index.css
.aqi-value {text-align: center;font-size: 65px;color: #f0ffff;width: 156px;height: 92px;top: 134px;left: 210px;
}
.aqi {text-align: center;color: #a2c4a2;width: 156px;height: 45px;top: 90px;left: 210px;
}
.airquality {top: 222px;text-align: center;width: 156px;height: 45px;left: 210px;
}
.image {top: 285px;left: 274px;width: 32px;height: 32px;
}
.location-text {text-align: center;color: #ffffff;width: 250px;height: 52px;font-size: 40px;left: 380px;top: 16px;
}
.container {flex-direction: column;height: 480px;width: 960px;
}
.circle-progress {center-x: 128px;center-y: 128px;radius: 128px;startAngle: 198;totalAngle: 320;strokeWidth: 24px;width: 256px;height: 256px;left: 160px;top: 58px;
}
.detail {width: 256px;height: 265px;left: 544px;top: 58px;flex-direction: column;
}
.text-wrapper {width: 256px;height: 35px;margin-top: 6px;
}
.gas-name {width: 128px;height: 35px;text-align: left;
}
.gas-value {width: 128px;height: 35px;text-align: right;
}
.btn {width: 180px;height: 50px;margin-top: 6px;margin-left: 38px;background-color: #1a1a1a;color: #1085CE;
}
.footer {top: 326px;width: 960px;height: 28px;
}
.header {width: 960px;height: 72px;
}
.back {width: 36px;height: 36px;margin-left: 39px;margin-top: 23px;
}
.title {width: 296px;height: 40px;margin-top: 20px;margin-left: 21px;color: #e6e6e6;
}
.swiper {height: 385px;width: 960px;
}
.images {width: 60px;height: 15px;margin-left: 450px;
}
.update-time {width: 480px;height: 28px;font-size: 20px;color: #A9A9A9;text-align: right;
}
.info-source {width: 450px;height: 28px;font-size: 20px;color: #A9A9A9;text-align: left;margin-left: 24px;
}
.circle-div {width: 12px;height: 12px;border-radius: 6px;
}
3.9 实现页面逻辑
修改index.js
,绑定页面数据data
。初始化时,根据不同的数值显示不同的字体和图片onInit
。实现页面跳转openDetail
,将当前页面索引传递给detail
页面。滑动触发后swiperChange
改变指示位置。
//引入router模块,用户页面跳转
import router from'@system.router'
import app from '@system.app'export default {
//定义参数data: {//页面绑定数据textColor1: "#00ff00",textColor2: "#00ff00",bgColor1: "#669966",bgColor2: "#669966",//默认是第一页swiperPage: 0,percent1: 10,percent2: 90,iconUncheckedColor: '#262626',iconcheckedColor: '#ffffff',iconcheckedBR: '6px',src1: "common/cloud_green.png",src2: "common/cloud_green.png",airData: [{location: "HangZhou",airQuality: "Good",detailData: 10},{location: "ShangHai",airQuality: "Unhealth",detailData: 90}]},onInit () {//根据数值的不同,设置不同的字体、背景颜色和图片if(this.airData[0].detailData > 100){this.src1 = 'common/cloud_red.png';this.textColor1 = '#ff0000';this.bgColor1 = '#9d7462';} else if(50 < this.airData[0].detailData && this.airData[0].detailData <= 100){this.src1 = 'common/cloud_yellow.png';this.textColor1 = '#ecf19a';this.bgColor1 = '#9d9d62';}if(this.airData[1].detailData > 100){this.src2 = 'common/cloud_red.png';this.textColor2 = '#ff0000';this.bgColor2 = '#9d7462';} else if(50 < this.airData[1].detailData && this.airData[1].detailData <= 100){this.src2 = 'common/cloud_yellow.png';this.textColor2 = '#ecf19a';this.bgColor2 = '#9d9d62';}if(this.selectedCityIndex){this.swiperPage = this.selectedCityIndex;if(this.swiperPage == 0){this.iconcheckedColor = '#ffffff';this.iconUncheckedColor = '#262626';}else{this.iconcheckedColor = '#262626';this.iconUncheckedColor = '#ffffff';}}},//跳转到详情页面openDetail () {router.replace({uri: 'pages/detail/detail',params: {selectedCityIndex:this.swiperPage}});},//退出应用exitApp(){console.log('start exit');app.terminate();console.log('end exit');},//swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中swiperChange (e) {this.swiperPage = e.index;if(e.index == 0){this.iconcheckedColor = '#ffffff';this.iconUncheckedColor = '#262626';}else{this.iconcheckedColor = '#262626';this.iconUncheckedColor = '#ffffff';}}
}
预览效果如下:
4. 开发详情页
详情页以图表的形式展示一周内空气质量指标值。本页面由两部分组成:标题栏和图表栏;在图表栏,考虑显示效果,我们使用多个div
替代chart
组件来实现图表功能。
4.1 添加标题栏
修改 entry/src/main/js/default/pages/detail/detail.hml
<div class="container"><div class="header" onclick="backMain"><image class="back" src="common/ic_back.png"></image><text class="title">历史记录</text></div><list class="chart-list"></list>
</div>
4.2 添加图表栏
添加城市位置到list-item-title
,图表到list-item-chart
<list class="chart-list"><list-item class="list-item-title"><text class="location">{{location}}</text></list-item><list-item class="list-item-chart"></list-item>
</list>
4.3 添加图表
<div class="chart-wrapper" style="margin-left: 128px;"><text class="gas-name">CO</text><div class="chart"><div class="chart-item" style="height: 78px;background-color: #00ff00;"></div><div class="chart-item" style="height: 52px;background-color: #00ff00;"></div><div class="chart-item" style="height: 155px;background-color: #ff0000;"></div><div class="chart-item" style="height: 134px;background-color: #ff0000;"></div><div class="chart-item" style="height: 98px;background-color: #FF7500;"></div><div class="chart-item" style="height: 88px;background-color: #FF7500;"></div><div class="chart-item" style="height: 144px;background-color: #ff0000;"></div></div><div class="white-line"></div><div class="week"></div>
</div>
4.4 添加样式
.location {text-align: center;color: #ffffff;width: 960px;height: 52px;font-size: 40px;
}
.container {height: 480px;width: 960px;flex-direction: column;
}.header {width: 960px;height: 72px;
}.back {width: 36px;height: 36px;margin-left: 39px;margin-top: 23px;
}.title {width: 296px;height: 40px;margin-top: 20px;margin-left: 21px;color: #e6e6e6;
}.chart-list {width: 960px;height: 408px;
}.list-item-title {width: 960px;height: 52px;
}.list-item-chart {width: 960px;height: 280px;
}.chart-wrapper {width: 308px;height: 256px;flex-direction: column;
}.gas-name {width: 308px;height: 35px;text-align: left;
}.chart {width: 308px;height: 155px;margin-top: 10px;justify-content: flex-start;align-items: flex-end;
}.chart-item {width: 24px;margin-left: 18px;border-radius: 3px;
}.white-line {width: 308px;height: 2px;background-color: #ffffff;margin-top: 22px;
}.week {width: 308px;height: 17px;margin-top: 6px;border-color: #ffffff;border-radius: 2px;margin-top: 6px;
}.day {width: 26px;height: 17px;font-size: 10px;margin-left: 16px;text-align: center;
}
4.5 实现页面跳转
其中onclick="backMain"
为返回主页事件,根据传递的页面索引,显示不同的位置数据,detail.js
中的代码实现如下:
import router from '@system.router'export default {data: {location: ''},onInit() {if (this.selectedCityIndex === 0) {this.location = '杭州';} else {this.location = '上海';}},backMain() {router.replace({uri: 'pages/index/index',params: {selectedCityIndex: this.selectedCityIndex}});}
}
5. 模拟器调试
菜单Tools->HVD Manager
,可以打开云端的模拟器
注册华为开发者账号,授权登录后
就能看到模拟器列表了,相比beta
版只有Phone
、TV
和Wearable
三种,增加了不少的设备。
可惜还没有可用于smartVision
设备的模拟器,现阶段我们还只能烧录到设备中调试,总体上"富鸿蒙"的进度比较快,期待一波更新。
6. 编译打包
若开发手机端的App
,则需要申请证书,对应用程序进行签名。这样才能发布到应用市场,才被允许安装到真机上运行。
IPCamera
应用「暂时不支持签名模式」,所以需要将应用发布为未签名的应用安装包。
菜单Build->Buildo APP(s)/Hap(s)->Build Release Hap(s)
,生成Hap
文件。
输出文件为 build/outputs/hap/release/smartVision/entry-release-smartVision-unsigned.hap
,改名为MyUiApp.hap
便于安装。
7. 通过sdcard安装
7.1 复制安装包和工具
将IDE编译的未签名应用安装包和安装工具(Z:\openharmony\out\my_hi3516dv300\dev_tools
)放在sdcard
中,将sdcard
插入开发板卡槽。
7.2 禁用签名校验
应用安装默认要校验签名,需要执行以下命令,关闭签名校验。
./sdcard/dev_tools/bin/bm set -s disable
7.3 安装应用
./sdcard/dev_tools/bin/bm install -p /sdcard/MyUiApp.hap
8. 通过NFS安装
每次插拔sdcard
还是蛮不方便的,这里我们安装一个NFS
服务器,让鸿蒙系统能直接访问Win10
的目录,后续安装调试就会方便很多。
8.1 安装NFS服务器
我们先安装一个haneWIN NFS服务器
, 双击文末网盘里的nfs1169.exe
,一路下一步即可。
8.2 配置目录参数
编辑输出表文件,定义传输目录
# exports example# C:\ftp -range 192.168.1.1 192.168.1.10
# c:\public -public -readonly
# c:\tools -readonly 192.168.1.4D:\PycharmProjects\aiLearn\Harmony\tftp -public -name:nfs
8.3 重启服务
右键管理员权限,重启所有服务,让配置生效。
8.4 设置防火墙
防火墙设置111、1058、2049
这些端口的TCP
和UDP
,入站规则放行。
8.5 鸿蒙上挂载目录
主电脑的ip
地址为192.168.1.57
,NFS
服务的别名为nfs
,对应的目录为D:\PycharmProjects\aiLearn\Harmony\tftp
mkdir nfs
mount 192.168.1.57:/nfs /nfs nfs
挂载到鸿蒙的刚新建的 /nfs
目录下,我们可以复制安装包和安装工具
8.6 安装应用
cd nfs
./dev_tools/bin/bm install -p MyUiApp.hap
前面做了这么多的铺垫,后续开发只要复制hap
安装包,直接一条命令安装即可,非常方便。
运行程序
安装完成后,点击桌面上的MyUiApp
就能看见界面效果了。
Js UI框架
对开发者还是比较友好的,有小程序或快应用的开发经验,上手应该都比较顺滑。
不过HarmonyOS Device
的支持库精简的非常严重,例如网络访问的@system.request
和@system.fetch
都不可用,这些功能在“富鸿蒙”的设备上开发就会比较方便。
资料下载
本期相关文件资料,可在公众号“深度觉醒”,后台回复:“ohos06”,获取下载链接。
下一篇
本期主要介绍了一下JS框架下的界面开发,
下一篇我们将尝试熟悉更多的设备能力,
并打通从框架用户态到驱动内核态之间的联系,
敬请期待...
往期推荐
用鸿蒙开发AI应用(HDF 驱动补光灯)
用鸿蒙开发AI应用(Helloworld)
用鸿蒙开发AI应用(软件篇)
用鸿蒙开发AI应用(六)UI篇相关推荐
- 用鸿蒙开发AI应用(五)HDF 驱动补光灯
前言 上一篇,我们在鸿蒙上运行了第一个程序,这一篇我们来编写一个驱动开启摄像头的红外补光灯,顺便熟悉一下鸿蒙上的 HDF 驱动开发. 硬件准备 先查一下原理图(具体可参考第一篇的硬件资料),找到红外灯 ...
- Unity关于Oculus Quest2 入门开发:(五)基于XR Interaction Toolkit0.10.0开发交互功能之UI篇
使用过Unity开发过VR的同学知道,UI分为两大类:渲染在摄像机上的和不渲染在摄像机上的也就是WorldSpace,当然Oculus Q2也一样,它需要的也是world类型的. 第一步:配置Ocul ...
- 鸿蒙下开发智能电视应用,用鸿蒙开发AI应用(六)UI篇
前言 上一篇,我们在鸿蒙上写了一个HDF驱动并操作了一下LED硬件,这一篇我们来尝试一下构建一个有简单界面的App,体验一下鸿蒙的前端开发流程. 环境准备 1. 安装DevEco Studio 解压相 ...
- iOS开发UI篇—UIWindow简单介绍
iOS开发UI篇-UIWindow简单介绍 一.简单介绍 UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow iOS程序启动完毕后,创建的第一个视图控件就是UIWi ...
- EnjoyingSoft之Mule ESB开发教程第六篇:Data Transform - 数据转换
目录 1. 数据转换概念 2. 数据智能感知 - DataSense 3. 简单数据转换组件 3.1 Object to JSON 3.2 JSON to XML 3.3 JSON to Object ...
- 基于小熊派的HarmonyOS鸿蒙开发教程——内核篇
复习时间:貌似很遥远呀!(未定期) 基于小熊派的鸿蒙开发内核篇 一.CMSIS-RTOS2接口 二.HarmonyOS内核开发-任务管理 三.HarmonyOS内核开发-定时器管理 定时器基本概念 定 ...
- iOS开发UI篇—transframe属性(形变)
iOS开发UI篇-transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移.缩放比例和旋转角度 常用的创建transform结构体方法分两 ...
- iOS开发UI篇—多控制器和导航控制器简单介绍
iOS开发UI篇-多控制器和导航控制器简单介绍 一.多控制器 一个iOS的app很少只由一个控制器组成,除非这个app极其简单.当app中有多个控制器的时候,我们就需要对这些控制器进行管理 有多个vi ...
- [分享]iOS开发-UI篇:CAlayer层的属性
iOS开发UI篇-CAlayer层的属性 一.position和anchorPoint 1.简单介绍 CALayer有2个非常重要的属性:position和anchorPoint @property ...
最新文章
- 计算机音乐谱打上花火,原神乐谱打上花火
- 【洛谷 P2464】[SDOI2008]郁闷的小J(线段树)
- Oracle本地管理对照数据字典管理表空间
- android 串口一直打开_android 如何打开串口以及与串口通讯
- .md是什么文件_Element-UI源码阅读之md显示到页面
- Perhaps you are running on a JRE rather than a JDK? 关于 idea maven 缓存的问题 清理 idea maven 缓存
- 输入2个正整数lower和upper(lower_题库 | 华为研发工程师编程题型介绍及解析 第 2 期...
- 红帽linux lnmp搭建,RedHat/CentOs系统搭建lnmp环境
- 用python批量下载modis数据的速度怎么样_MODIS数据的简介和下载(五)——应用密钥的Python脚本下载...
- 计算机菜单界面无法缩小怎么办,如何解决Win10个性化设置最小化任务栏后不能弹出的问题?...
- GD32系列外部中断
- 51单片机:串口通信
- R语言 使用getGEO()直接进行差异表达分析并显示Entrez_id和Symbol_id
- FTP网络服务器 Xlight+FlashFXP
- 计算机安全群,大开眼界||斯坦福大学信息安全课程群
- linux查询服务器域名解析记录
- HDMI设计1--HDMI 1.4b SPEC的阅读个人总结
- AEJoy —— 彻底搞懂 AE 各种 loop* 表达式【二】
- 人均 3.6万行代码, C++ 成最烫手山药:腾讯首度披露技术研发数据!
- ASO优化优缺点各是什么?带你学会常见的优化手段
热门文章
- 研究生中山大学计算机学院分数线,中山大学2017年硕士研究生复试分数线
- 新闻客户端的三种模式和四种活法
- 【NOIP2014】飞扬的小鸟 背包dp
- VRRP协议详解-----(1)
- 重置功能怎么实现java_java实现忘记密码功能
- linux(debian)下的vim diff时 报错E97解决,文件夹对比meld,beyond compare
- linux改完权限后 自动恢复,linux文件或目录权限修改后如何恢复(备份了权限就能恢复)...
- 【零基础学Python】海龟画图篇 :第十九节--海龟画图实际应用|用法总结
- 开源全景图查看器-360player_v3.0更新
- 对lim me → ∞ = you的理解