如何实现手机遥控端关机按钮同时关闭TV端和手机端界面

目前家庭电视机主要通过其自带的遥控器进行操控,实现的功能较为单一。例如,当我们要在TV端搜索节目时,电视机在遥控器的操控下往往只能完成一些字母或数字的输入,而无法输入其他复杂的内容。分布式遥控器将手机的输入能力和电视遥控器的遥控能力结合为一体,从而快速便捷操控电视。

分布式遥控器的实现基于OpenHarmony的分布式能力和RPC通信能力,UI使用eTS进行开发。如下图所示,分别用两块开发板模拟TV端和手机端。

  1. 分布式组网后可以通过TV端界面的Controller按钮手动拉起手机端的遥控界面,在手机端输入时会将输入的内容同步显示在TV端搜索框,点击搜索按钮会根据输入的内容搜索相关节目。
  2. 还可以通过点击方向键(上下左右)将焦点移动到我们想要的节目上,再点击播放按钮进行播放,按返回按钮返回TV端主界面。
  3. 同时还可以通过手机遥控端关机按钮同时关闭TV端和手机端界面。

UI效果图如下:

图1 TV端主页默认页面

图2 手机端遥控页面

  • 图3 TV端视频播放页面

说明: 本示例涉及使用系统接口,需要手动替换Full SDK才能编译通过

2.搭建OpenHarmony环境

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。

      以3.1版本为例:

2.搭建烧录环境。

    1. 完成DevEco Device Tool的安装
    2. 完成RK3568开发板的烧录

3.搭建开发环境。

    1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”),选择JS或者eTS语言开发。
    3. 工程创建完成后,选择使用真机进行调测。

3.分布式组网

本章节以系统自带的音乐播放器为例(具体以实际的应用为准),介绍如何完成两台设备的分布式组网。

  1. 硬件准备:准备两台烧录相同的版本系统的RK3568开发板A、B。
  2. 开发板A、B连接同一个WiFi网络。

      打开设置-->WLAN-->点击右侧WiFi开关-->点击目标WiFi并输入密码。

3.将设备A,B设置为互相信任的设备。

  • 找到系统应用“音乐”。

  • 设备A打开音乐,点击左下角流转按钮,弹出列表框,在列表中会展示远端设备的id。选择远端设备B的id,另一台开发板(设备B)会弹出验证的选项框。

  • 设备B点击允许,设备B将会弹出随机PIN码,将设备B的PIN码输入到设备A的PIN码填入框中。

  1. 配网完毕。

4.代码结构解读

本篇Codelab只对核心代码进行讲解,首先来介绍下整个工程的代码结构:

  • MainAbility:
    • model:数据模型。
      • RemoteDeviceModel.ets:获取组网内的设备列表模型。
      • PicData.ets:图片信息数据。
      • PicDataModel.ets:图片信息模型。
      • ConnectModel.ets:连接远端Service和发送消息模型。
    • pages:存放TV端各个页面。
      • TVindex.ets:TV端主页面。
      • VideoPlay.ets:TV端视频播放页面。
  • PhoneAbility:存放应用手机控制端主页面。
    • pages/PhoneIndex.ets:手机控制端主页面。
  • ServiceAbility:存放ServiceAbility相关文件。
    • service.ts:service服务,用于跨设备连接后通讯。
  • resources :存放工程使用到的资源文件。
    • resources/rawfile:存放工程中使用的图片资源文件。
  • config.json:配置文件。

5.实现TV端界面

在本章节中,您将学会开发TV端默认界面和TV端视频播放界面,示意图参考第一章图1和图3所示。

建立数据模型,将图片ID、图片源、图片名称和视频源绑定成一个数据模型。详情代码可以查看MainAbility/model/PicData.ets和MainAbility/model/PicDataModel.ets两个文件。

  1. 实现TV端默认页面布局和样式。
  • 在MainAbility/pages/TVIndex.ets 主界面文件中添加入口组件。页面布局代码如下:
// 入口组件
@Entry
@Component
struct Index {
  private letters: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
  private source: string
  @State text: string = ''
  @State choose: number = -1
  build() {
    Flex({ direction: FlexDirection.Column }) {
      TextInput({text: this.text, placeholder: 'Search' })
        .onChange((value: string) => {
          this.text = value
        })
      Row({space: 30}) {
        Text('Clear')
          .fontSize(16)
          .backgroundColor('#ABB0BA')
          .textAlign(TextAlign.Center)
          .onClick(() => {
            this.text = ''
          })
          .clip(true)
          .borderRadius(10)
        Text('Backspace')
          .fontSize(16)
          .backgroundColor('#ABB0BA')
          .textAlign(TextAlign.Center)
          .onClick(() => {
            this.text = this.text.substring(0, this.text.length - 1)
          })
          .clip(true)
          .borderRadius(10)
        Text('Controller')
          .fontSize(16)
          .backgroundColor('#ABB0BA')
          .textAlign(TextAlign.Center)
          .onClick(() => {
            ......
          })
          .clip(true)
          .borderRadius(10)
      }
      Grid() {
        ForEach(this.letters, (item) => {
          GridItem() {
            Text(item)
              .fontSize(20)
              .backgroundColor('#FFFFFF')
              .textAlign(TextAlign.Center)
              .onClick(() => {
                this.text += item
                })
              .clip(true)
              .borderRadius(5)
          }
        }, item => item)
      }
      .rowsTemplate('1fr 1fr 1fr 1fr')
      .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr')
      .columnsGap(8)
      .rowsGap(8)
      .width('75%')
      .height('25%')
      .margin(5)
      .backgroundColor('#D2D3D8')
      .clip(true)
      .borderRadius(10)
      Grid() {
        ForEach(this.picItems, (item: PicData) => {
          GridItem() {
            PicGridItem({ picItem: item })
          }
        }, (item: PicData) => item.id.toString())
      }
      .rowsTemplate('1fr 1fr 1fr')
      .columnsTemplate('1fr 1fr')
      .columnsGap(5)
      .rowsGap(8)
      .width('90%')
      .height('58%')
      .backgroundColor('#FFFFFF')
      .margin(5)
    }
    .width('98%')
    .backgroundColor('#FFFFFF')
  }
}
  • 其中PicGridItem将PicItem的图片源和图片名称绑定,实现代码如下:
// 九宮格拼图组件
@Component
struct PicGridItem {
  private picItem: PicData
  build() {
    Column() {
      Image(this.picItem.image)
        .objectFit(ImageFit.Contain)
        .height('85%')
        .width('100%')
        .onClick(() => {
          ......
          })
        })
      Text(this.picItem.name)
        .fontSize(20)
        .fontColor('#000000')
    }
    .height('100%')
    .width('90%')
  }
}

2.实现TV端视频播放界面。

  • 在MainAbility/pages/VideoPlay.ets 文件中添加组件。页面布局代码如下:
import router from '@system.router'
@Entry
@Component
struct Play {
// 取到Index页面跳转来时携带的source对应的数据。
  private source: string = router.getParams().source
  build() {
    Column() {
      Video({
        src: this.source,
      })
        .width('100%')
        .height('100%')
        .autoPlay(true)
        .controls(true)
    }
  }
}
  • 在MainAbility/pages/TVIndex.ets中,给PicGridItem的图片添加点击事件,点击图片即可播放PicItem的视频源。实现代码如下:
Image(this.picItem.image)
        ......
        .onClick(() => {
          router.push({
            uri: 'pages/VideoPlay',
            params: { source: this.picItem.video }
          })
        })

6.实现手机遥控端界面

在本章节中,您将学会开发手机遥控端默认界面,示意图参考第一章图2所示。

  • PhoneAbility/pages/PhoneIndex.ets 主界面文件中添加入口组件。页面布局代码如下:
@Entry
@Component
struct Index {
  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
      Row() {
        Image($rawfile('TV.png'))
          .width(25)
          .height(25)
        Text('华为智慧屏').fontSize(20).margin(10)
      }
      // 文字搜索框
      TextInput({ placeholder: 'Search' })
        .margin(20)
        .onChange((value: string) => {
          if (connectModel.mRemote){
            ......
          }
        })
      Grid() {
        GridItem() {
      // 向上箭头
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($rawfile('up.png')).width(80).height(80)
          }
          .onClick(() => {
            ......
          })
          .width(80)
          .height(80)
          .backgroundColor('#FFFFFF')
        }
        .columnStart(1)
        .columnEnd(5)
        GridItem() {
      // 向左箭头
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($rawfile('left.png')).width(80).height(80)
          }
          .onClick(() => {
            ......
          })
          .width(80)
          .height(80)
          .backgroundColor('#FFFFFF')
        }
        GridItem() {
      // 播放键
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($rawfile('play.png')).width(60).height(60)
          }
          .onClick(() => {
            ......
          })
          .width(80)
          .height(80)
          .backgroundColor('#FFFFFF')
        }
        GridItem() {
      // 向右箭头
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($rawfile('right.png')).width(70).height(70)
          }
          .onClick(() => {
            ......
          })
          .width(80)
          .height(80)
          .backgroundColor('#FFFFFF')
        }
        GridItem() {
      // 向下箭头
          Button({ type: ButtonType.Circle, stateEffect: true }) {
            Image($rawfile('down.png')).width(70).height(70)
          }
          .onClick(() => {
            ......
          })
          .width(80)
          .height(80)
          .backgroundColor('#FFFFFF')
        }
        .columnStart(1)
        .columnEnd(5)
      }
      .rowsTemplate('1fr 1fr 1fr')
      .columnsTemplate('1fr 1fr 1fr')
      .backgroundColor('#FFFFFF')
      .margin(10)
      .clip(new Circle({ width: 325, height: 325 }))
      .width(350)
      .height(350)
      Row({ space:100 }) {
        // 返回键
        Button({ type: ButtonType.Circle, stateEffect: true }) {
          Image($rawfile('return.png')).width(40).height(40)
        }
        .onClick(() => {
          ......
        })
        .width(100)
        .height(100)
        .backgroundColor('#FFFFFF')
        // 关机键
        Button({ type: ButtonType.Circle, stateEffect: true }) {
          Image($rawfile('off.png')).width(40).height(40)
        }
        .onClick(() => {
          ......
        })
        .width(100)
        .height(100)
        .backgroundColor('#FFFFFF')
        // 搜索键
        Button({ type: ButtonType.Circle, stateEffect: true }) {
          Image($rawfile('search.png')).width(40).height(40)
        }
        .onClick(() => {
          ......
        })
        .width(100)
        .height(100)
        .backgroundColor('#FFFFFF')
      }
      .padding({ left:100 })
    }
    .backgroundColor('#E3E3E3')
  }
}

7.实现分布式拉起和RPC通信

在本章节中,您将学会如何拉起在同一组网内的设备上的FA,并且连接远端Service服务。

  1. 首先通过TV端拉起手机端界面,并将本端的deviceId发送到手机端。
  • 点击TV端主页上的"Controller"按钮,增加.onClick()事件。调用RegisterDeviceListCallback()发现设备列表,并弹出设备列表选择框CustomDialogExample,选择设备后拉起远端FA。CustomDialogExample()代码如下:
// 设备列表弹出框
@CustomDialog
struct CustomDialogExample {
  @State editFlag: boolean = false
  controller: CustomDialogController
  cancel: () => void
  confirm: () => void
  build() {
    Column() {
      List({ space: 10, initialIndex: 0 }) {
        ForEach(DeviceIdList, (item) => {
          ListItem() {
            Row() {
              Text(item)
                .width('87%')
                .height(50)
                .fontSize(10)
                .textAlign(TextAlign.Center)
                .borderRadius(10)
                .backgroundColor(0xFFFFFF)
                .onClick(() => {
                  onStartRemoteAbility(item);
                  this.controller.close();
                })
            }
          }.editable(this.editFlag)
        }, item => item)
      }
    }.width('100%').height(200).backgroundColor(0xDCDCDC).padding({ top: 5 })
  }
}
  • 点击设备弹出框内的Text组件会调用onStartRemoteAbility()方法拉起远端FA(手机端),将TV端的deviceId传给手机端,并连接手机端的Service。因此在featureAbility.startAbility()成功的回调中也要调用onConnectRemoteService()方法。这里将连接远端Service和发送消息抽象为ConnectModel,详细代码可查看MainAbility/model/ConnectModel.ets文件中onConnectRemoteService()方法。onStartRemoteAbility()方法的代码如下:
function onStartRemoteAbility(deviceId) {
  AuthDevice(deviceId);
  let numDevices = remoteDeviceModel.deviceList.length;
  if (numDevices === 0) {
    prompt.showToast({
      message: "onStartRemoteAbility no device found"
    });
    return;
  }
  var params = {
    remoteDeviceId: localDeviceId
  }
  var wantValue = {
    bundleName: 'com.example.helloworld0218',
    abilityName: 'com.example.helloworld0218.PhoneAbility',
    deviceId: deviceId,
    parameters: params
  };
  featureAbility.startAbility({
    want: wantValue
  }).then((data) => {
    // 拉起远端后,连接远端service
    connectModel.onConnectRemoteService(deviceId)
  });
}
  • 需要注意的是,配置文件config.json中ServiceAbility的属性visible要设置为true,代码如下:
"abilities": [
      ...
      {
        "visible": true,
        "srcPath": "ServiceAbility",
        "name": ".ServiceAbility",
        "icon": "$media:icon",
        "srcLanguage": "ets",
        "description": "$string:description_serviceability",
        "type": "service"
      }
],

2.成功拉起手机端界面后,通过接收TV端传过来的deviceId连接TV端的Service。在手机端的生命周期内增加aboutToAppear()事件,在界面被拉起的时候读取对方的deviceId并调用onConnectRemoteService()方法,连接对方的Service,实现代码如下:

async aboutToAppear() {
    await featureAbility.getWant((error, want) => {
      // 远端被拉起后,连接对端的service
      if (want.parameters.remoteDeviceId) {
        let remoteDeviceId = want.parameters.remoteDeviceId
        connectModel.onConnectRemoteService(remoteDeviceId)
      }
    });
  }

3.建立一个ServiceAbility处理收到的消息并发布公共事件,详细代码请看ServiceAbility/service.ts文件。TV端订阅本端Service的公共事件,并接受和处理消息。

  • 创建SubscribeEvent(),实现代码如下:
subscribeEvent() {
    let self = this;
    // 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
    var subscriber;
    // 订阅者信息
    var subscribeInfo = {
      events: ["publish_change"],
      priority: 100
    };
    // 设置有序公共事件的结果代码回调
    function SetCodeCallBack() {
    }
    // 设置有序公共事件的结果数据回调
    function SetDataCallBack() {
    }
    // 完成本次有序公共事件处理回调
    function FinishCommonEventCallBack() {
    }
    // 订阅公共事件回调
    function SubscribeCallBack(err, data) {
      let msgData = data.data;
      let code = data.code;
      // 设置有序公共事件的结果代码
      subscriber.setCode(code, SetCodeCallBack);
      // 设置有序公共事件的结果数据
      subscriber.setData(msgData, SetDataCallBack);
      // 完成本次有序公共事件处理
      subscriber.finishCommonEvent(FinishCommonEventCallBack)
      // 处理接收到的数据data
      ......
    // 创建订阅者回调
    function CreateSubscriberCallBack(err, data) {
      subscriber = data;
      // 订阅公共事件
      commonEvent.subscribe(subscriber, SubscribeCallBack);
    }
    // 创建订阅者
    commonEvent.createSubscriber(subscribeInfo, CreateSubscriberCallBack);
  }
}
  • 在TV端的生命周期内增加aboutToAppear()事件,订阅公共事件,实现代码如下:
async aboutToAppear() {
    this.subscribeEvent();
  }

4.成功连接远端Service服务后,在手机遥控器端进行按钮或者输入操作都会完成一次跨设备通讯,消息的传递是由手机遥控器端的FA传递到TV端的Service服务。这里将连接远端Service和发送消息抽象为ConnectModel,详细代码可查看MainAbility/model/ConnectModel.ets文件中sendMessageToRemoteService()方法。

8.设置遥控器远端事件

手机端应用对TV端能做出的控制有:向上移动、向下移动、向左移动、向右移动、确定、返回、关闭。在手机端按键上增加点击事件,通过sendMessageToRemoteService()的方法发送到TV端Service。TV端根据发送code以及数据,进行数据处理,这里只展示TV端数据处理部分的核心代码:

// code = 1时,将手机遥控端search框内数据同步到TV端
if (code == 1) {
  self.text = data.parameters.dataList;
}
// code = 2时,增加选中图片效果
if (code == 2) {
  // 如果在图片序号范围内就选中图片,否则不更改
  var tmp: number = +data.parameters.dataList;
  if ((self.choose + tmp <= 5) && (self.choose + tmp >= 0)) {
    self.choose += tmp;
  }
}
// code = 3时,播放选中图片对应的视频
if (code == 3) {
  self.picItems.forEach(function (item) {
    if (item.id == self.choose) {
      router.push({
        uri: 'pages/VideoPlay',
        params: { source: item.video }
      })
    }
  })
}
// code = 4时,回到TV端默认页面
if (code == 4) {
  router.push({
    uri: 'pages/TVIndex',
  })
}
// code = 5时,关闭程序
if (code == 5) {
  featureAbility.terminateSelf()
}
// code = 6时,搜索图片名称并增加选中特效
if (code == 6) {
  self.picItems.forEach(function (item) {
    if (item.name == self.text) {
      self.choose = Number(item.id)
    }
  })
}

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了几套最新版的HarmonyOS NEXT学习资源

获取完整版高清学习路线,请点击→《HarmonyOS教学视频

HarmonyOS教学视频

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取白皮书:请点击→《鸿蒙生态应用开发白皮书V2.0PDF

在这里插入图片描述

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. .……

在这里插入图片描述


二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

在这里插入图片描述

三、如何快速入门?《做鸿蒙应用开发到底学习些啥?》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. .……

在这里插入图片描述


四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. .……

在这里插入图片描述


五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 7.网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. .……

在这里插入图片描述


更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

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

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

相关文章

pandas读写excel,csv

1.读excel 1.to_dict() 函数基本语法 DataFrame.to_dict (self, orientdict , into ) --- 官方文档 函数种只需要填写一个参数&#xff1a;orient 即可 &#xff0c;但对于写入orient的不同&#xff0c;字典的构造方式也不同&#xff0c;官网一共给出了6种&#xff0c…

为什么3D开发要用三维模型格式转换工具HOOPS Exchange?

在当今数字化时代&#xff0c;3D技术在各个行业中扮演着愈发重要的角色&#xff0c;从产品设计到制造、建筑、医疗保健等领域。然而&#xff0c;由于不同的软件和系统使用不同的3D模型格式&#xff0c;跨平台、跨系统之间的数据交换和共享变得十分复杂。为了解决这一难题&#…

利用Python进行数据清洗与预处理:Pandas的高级用法【第147篇—Pandas的高级用法】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 利用Python进行数据清洗与预处理&#xff1a;Pandas的高级用法 在数据科学和机器学习领域&…

浅浅迈入C++门槛

从今天起&#xff0c;我要开始hello&#xff0c;world。 往后更要做到&#xff0c;拳打数据结构&#xff0c;脚踢Linux。 这就是江湖人的风范。 拼搏百天&#xff0c;我要学希普拉斯普拉斯。 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许…

基于单片机的四旋翼飞行器的设计与实现

摘 要:四旋翼飞行器可以垂直升降,应用于军事和民用领域,在飞行器的设计中,结合单片机进行设计,可以提升整体性能。基于此,本文探究基于单片机的四旋翼飞行器设计与实现,探索飞行器的硬件设计和软件设计方案,并且对系统的角速度算法以及姿态控制算法进行测试,最后对系…

【题目】【网络系统管理】2019年全国职业技能大赛高职组计算机网络应用赛项H卷

极安云科专注职业教育技能竞赛培训4年&#xff0c;包含信息安全管理与评估、网络系统管理、网络搭建等多个赛项及各大CTF模块培训学习服务。本团队基于赛项知识点&#xff0c;提供完整全面的系统性理论教学与技能培训&#xff0c;成立至今持续优化教学资源与讲师结构&#xff0…

【QT+QGIS跨平台编译】之八十五:【QGIS_Gui跨平台编译】—【错误处理:Qt5UiTools - Qt5UiTools】

文章目录 一、错误信息二、错误处理 一、错误信息 二、错误处理 定位到Qt5iTools目录。(例如&#xff1a;/Users/lucky/Qt/5.15.2/clang_64/lib&#xff09; 拷贝libQt5UiTools.a&#xff0c;粘贴为&#xff1a;libQt5UiTools_debug.a

基于Matlab的视频人体动作识别,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

【HM】STM32F407 HAL库 PWM

PWM简介 脉冲宽度调制&#xff08;PWM&#xff09; 是一种数字信号&#xff0c;最常用于控制电路。该信号在预定义的时间和速度中设置为高&#xff08;5v或3.3v&#xff09;和低&#xff08;0v&#xff09;。通常&#xff0c;我们将PWM的高电平称为1&#xff0c;低电平为0。 …

解锁人工智能新境界:大模型工程与架构的深度探索

在当今世界&#xff0c;人工智能(AI)无处不在&#xff0c;它已经悄然改变了我们的生活方式。从自动驾驶汽车到智能音箱&#xff0c;从智能医疗系统到虚拟助手&#xff0c;AI的影子无处不在。而在这一切背后&#xff0c;是一个个巨大的数学模型在默默运转。这些模型就像是我们人…

excel所有知识点

1要加双引号 工作表&#xff08;.xlsx) 单击右键→插入&#xff0c;删除&#xff0c;移动、重命名、复制、设置标签颜色&#xff0c;选定全部工作表 工作表的移动&#xff1a;两个表打开→右键→移动&#xff08;如果右键是灰色的&#xff0c;可能是保护工作表了&#xff09…

JAVA安全(偏基础)

SQL注入 SQLI(SQL Injection)&#xff0c; SQL注入是因为程序未能正确对用户的输入进行检查&#xff0c;将用户的输入以拼接的方式带入SQL语句&#xff0c;导致了SQL注入的产生。攻击者可通过SQL注入直接获取数据库信息&#xff0c;造成信息泄漏。 JDBC JDBC有两个方法获取s…

鸿蒙Harmony应用开发—ArkTS-全局UI方法(列表选择弹窗)

列表弹窗。 说明&#xff1a; 从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 本模块功能依赖UI的执行上下文&#xff0c;不可在UI上下文不明确的地方使用&#xff0c;参见UIContext说明。 从API version 10开始&#xff0…

hadoop学习笔记

hadoop概述 Apache Hadoop 为可靠的&#xff0c;可扩展的分布式计算开发开源软件。作为一个数据框架允许使用简单的编程模型跨计算机群集分布式处理大型数据集&#xff08;海量的数据&#xff09;。分别由一下三个模块组成&#xff1a; 1、Hadoop分布式文件系统&#xff08;HDF…

flink join的分类

带窗口的join 下图是固定窗口,同样的还有滑动窗口和会话窗口join DataStream<Integer> orangeStream = ...; DataStream<Integer> greenStream = .

报表生成器FastReport .Net用户指南:关于脚本(下)

FastReport的报表生成器&#xff08;无论VCL平台还是.NET平台&#xff09;&#xff0c;跨平台的多语言脚本引擎FastScript&#xff0c;桌面OLAP FastCube&#xff0c;如今都被世界各地的开发者所认可&#xff0c;这些名字被等价于“速度”、“可靠”和“品质”,在美国&#xff…

走进redisson

这里作者将大家走进redisson&#xff0c;读完这篇相信加深你对redisson的获取锁&#xff0c;重入&#xff0c;超时&#xff0c;看门狗&#xff0c;发布订阅等原理和功能的理解。 本文将深入原理代码&#xff0c;给出每行代码的意义以及最后的效果&#xff0c;过程有些枯燥&…

GitHub Copilot怎么取消付费?

0. 前言 GitHub Copilot非常好用&#xff0c;还没有使用过的同学可以参考教程白嫖一个月&#xff1a;【保姆级】VsCode 安装GitHub Copilot实操教程 GitHub Copilot每月10美元的费用对于一些用户来说可能是一笔不小的开销。如果你已经完成了GitHub Copilot的免费试用&#xf…

在conda下的sklearn库安装

比较坑的是它这个库在conda下不叫这个名字&#xff0c;所以直接conda install sklearn是不行的&#xff0c;输入下面的指令就能直接安装啦。 conda install scikit-learn

【数据结构】猛猛干7道链表OJ

前言知识点 链表的调试技巧 int main() {struct ListNode* n1(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3(struct ListNode*)malloc(sizeof(struc…