3516遥控3861智能小车系列(一)C++开发界面应用

Wesley13
• 阅读 466

目录:

1.harmonyos的设备开发的图形图像子系统

2.开始正式该应用的实现过程

3.总结

下载附件(包含源码包+hap包)

老规矩先上该应用的演示视频:https://harmonyos.51cto.com/show/3006#kyzg

首先立flag:用3516做一款独一无二的遥控器,然后用这款遥控器去尽情的操纵3861这款智能小车。第一呢,肯定不能做的太粗糙了,打工人也要有点儿追求的。第二呢,围绕着源码,发现一些更多的好东西,比如这次C++界面开发中大多数API,官方是暂未给出的,这就需要是我去摸索源码。其中最重要的一点,我想看看能否在3516和3861组成局域网之后,能否利用分布式软总线能力去调用(当然,这个可能会吹牛,毕竟钊哥说他目前还没调通)。

flag立完了,这个能不能实现.....我尽力吧

首先呢,大家得搭好3516的环境,我最近之所以鸽了这么长时间没有发文章。也有一部分这个原因,因为我本身用的系统是ubuntu20.04,然后在其上搭windows虚拟机来烧系统以及刷应用。我在这个过程中是“编代码3分钟,刷系统3天”,这里我也分享一下我遇到的坑,如果大家也有我这种环境配置的话,希望可以帮助到大家。最开始的时候,我是用的virtualBox虚拟机来搭的windows,这个windows来玩3861的时候别提多顺畅了,当我以为3516也会一样顺畅的时候,我发现我错了,装上3516的驱动后,我的windows开始了无限自动重启模式,我在尝试着修复无果后,一度想着放弃....但是作为一名合格的码农,怎么能随便放弃呢!然后抱着试试看的态度,我装了一个vmware,没想到啊,真是“山重水复疑无路,柳暗花明又一村”。3516的环境就这样被搭好了!好了,说了这么长时间的废话:总结来说就是如果你的本体是linux,那么你在装window的时候虚拟机要选用vmware,不要用virtualBox(PS:我这里本体用了linux,不是装叉,因为工作的原因导致我毕业之后没就用过window,慢慢也就习惯了linux了)

然后呢,具体搭建环境的过程,社区置顶处有文章介绍,在window为本体,linux做虚拟机的情况下,难度还是要小很多的,所以各位大佬也不用太担心这个过程。

好的,作为这个系列的第一篇,也就是实现这个目标的第一步:我先在3516上做一个遥控器的应用,当然这个应用不追求什么完美,但至少也得能看得过去,所以我自认为我做的还是很认真的,演示视频链接见开头,好不好看,大家可以留言评论一拨儿。

下面进入正题,我们来看C++的应用界面开发:

1.harmonyos的设备开发的图形图像子系统

首先发出来官网该方面资料介绍的链接https://device.harmonyos.com/cn/docs/develop/subsystems/oem_subsys_graphic_des-0000001051677150#ZH-CN_TOPIC_0000001051770388__section73736284117

HarmonyOS图形系统,提供基础UI组件和容器类组件,包括button、image、label、list、animator、scroll view、swipe view、font、clock、chart、canvas、slider、layout等。

不过呢,目前官网给出的示例还是十分有限的,如果想要按自己的想法去构思应用的话,很明显这些官方的介绍还是远远不够的,下面我给出这部分源码的代码位置:
其中绝大多数的头文件在:foundation/graphic/lite/interfaces/kits/ui/
其实foundation/graphic/就存放了源码中的图形模块,各位大佬可以尽情去相关模块源码中遨游,然后能给我点儿指导也是极好的。

在这里我们先整理一下,目前已经开放的,包括源码中已经有的图形模块可以分为两部分一部分是容器类组件,一部分是普通组件,其中容器类组件有如下图
普通类组件如下图:

3516遥控3861智能小车系列(一)C++开发界面应用

容器类组件:

3516遥控3861智能小车系列(一)C++开发界面应用

另外据我目前已有的探索结论是:一个主界面有一个RootView,使用GetWindowRootView来获得,大家可以把它看成一个界面中最大的容器类组件,然后大家就是把界面相关的容器类组件,普通类组件往上堆就可以。当然别的多界面的实现方式应该不同。

2.开始正式该应用的实现过程:

3516遥控3861智能小车系列(一)C++开发界面应用
如上图:大家可以看到这个整个界面的布局:其中左上角的小箭头是退出应用的,然后它的右边是一行文字动画,接着往下是两个label来显示当前遥控器的模式和小车的状态,紧接着是两个按钮。接下来是整个SWIPE容器组件,可以滑动来实现界面的切换。
下面就按照这个顺序来介绍:其中重点是小箭头的功能的实现和SWIPE容器组件的实现,别的么,其实不值一提。
2.1 退出应用功能的实现
PS:这个功能的实现,完全没有介绍,完全是自己看着源码琢磨出来的,并且我还发现了源码中这块儿写的有BUG,源码中会有点击不中的情况。
2.1.1 先拿代码把这个图标画出来:

static const char* const BACK_ICON_PATH = "/controlCar/assets/entry/resources/base/media/ic_back.png";
static char g_backIconAbsolutePath[MAX_PATH_LENGTH] = {0};
const char* pathHeader = GetSrcPath();
if(sprintf_s(g_backIconAbsolutePath,MAX_PATH_LENGTH,"%s%s",pathHeader,BACK_ICON_PATH) < 0){
    printf("GalleryAbilitySlice::OnStart | g_backIconAbsolutePath error");
    return;
}
    backIcon = new UIImageView();
    backIcon->SetPosition(0, 0);
    backIcon->SetSrc(g_backIconAbsolutePath);
    backIcon->SetTouchable(true);
    backIcon->Resize(40,40);

2.1.2 实现退出功能

    auto onClick = [this] (UIView& view, const Event& event) -> bool {
        TerminateAbility();
        return true;
    };
    backIconListener = new EventListener(onClick, nullptr);
    backIcon->SetOnClickListener(backIconListener);

2.2 字幕滚动

是不是觉得很难,刚开始我也觉得是,然并卵,太TM简单了,只需要调用SetLineBreakMode这个API就可以了,下面是这个组件的实现代码。

    label_title = new UILabel();
    label_title->SetPosition(280,0);
    label_title->Resize(500,40);
    label_title->SetTextColor(Color::Red());
    label_title->SetText("欢迎各位大佬使用本智能小车遥控器,希望各位大佬能玩的开心!");
    label_title->SetFont("SourceHanSansSC-Regular.otf",30);
    label_title->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE);

2.3 显示的两个label和两个button按钮

这个嘛,太简单了,就不解释了,直接来最简单的设置就可以了,见下面代码

    //设置显示遥控器模式状态label
    label_remote_state = new UILabel();
    label_remote_state->SetPosition(10,40);
    label_remote_state->Resize(300,40);
    label_remote_state->SetTextColor(Color::Green());
    label_remote_state->SetText("当前模式:基础模式");
    label_remote_state->SetFont("SourceHanSansSC-Regular.otf",20);

    //设置label
    label = new UILabel();
    label->SetPosition(300,40);
    label->SetStyle(STYLE_BACKGROUND_COLOR,Color::Gray().full);
    label->Resize(350,40);
    label->SetText("当前小车连接状态:正在检测中...");
    label->SetTextColor(Color::Green());
    label->SetFont("SourceHanSansSC-Regular.otf", 20);

    //设置连接小车按钮
    bt_connect = new UILabelButton();
    bt_connect->SetPosition(700,40,100,40);
    bt_connect->SetTextColor(Color::Green());
    bt_connect->SetText("连接小车");

    //设置断开连接按钮
    bt_disconnect = new UILabelButton();
    bt_disconnect->SetPosition(850,40,100,40);
    bt_disconnect->SetTextColor(Color::Green());
    bt_disconnect->SetText("断开连接");

2.3 整个SWIPE容器组件的实现

没错,这部分是整个应用实现的最困难处,文档中介绍基本等于没有,整个SWIPE容器实现的技术难点:应该是两点:
- 1.设置滑动回调类
- 2.在SWIPE使用了GridLayout来实现整个遥控器按钮的设计。

2.3.1 先看如何利用GridLayout来实现遥控器按钮的实现

    gridlayout = new GridLayout();
    gridlayout->SetPosition(0,0,900,400);
    gridlayout->SetRows(3);
    gridlayout->SetCols(5);
    gridlayout->SetLayoutDirection(LAYOUT_HOR);

    bt_left_one = new UILabelButton();
    bt_left_one->SetPosition(0,0,100,100);
    bt_left_one->SetVisible(false);

    bt_left_up = new UILabelButton();
    bt_left_up->SetPosition(0,0,100,100);
    bt_left_up->SetImageSrc(g_left_upAbsolutePath,g_left_upAbsolutePath);
    bt_left_up->SetImagePosition(0,0);
    bt_left_up->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_left_up->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_left_up->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_left_up->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_up = new UILabelButton();
    bt_up->SetPosition(0,0,100,100);
    bt_up->SetImageSrc(g_upAbsolutePath,g_upAbsolutePath);
    bt_up->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_up->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_up->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_up->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_right_up = new UILabelButton();
    bt_right_up->SetPosition(0,0,100,100);
    bt_right_up->SetImageSrc(g_right_upAbsolutePath,g_right_upAbsolutePath);
    bt_right_up->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_right_up->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_right_up->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_right_up->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_right_one = new UILabelButton();
    bt_right_one->SetPosition(0,0,100,100);
    bt_right_one->SetVisible(false);

    bt_left_two = new UILabelButton();
    bt_left_two->SetPosition(0,0,100,100);
    bt_left_two->SetVisible(false);

    bt_left = new UILabelButton();
    bt_left->SetPosition(0,0,100,100);
    bt_left->SetImageSrc(g_leftAbsolutePath,g_leftAbsolutePath);
    bt_left->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_left->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_left->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_left->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_stop = new UILabelButton();
    bt_stop->SetPosition(0,0,100,100);
    bt_stop->SetStyle(STYLE_BORDER_RADIUS,0);
    bt_stop->SetImageSrc(g_stopAbsolutePath,g_stopAbsolutePath);
    bt_stop->SetStyle(STYLE_BACKGROUND_COLOR,Color::White().full);

    bt_right = new UILabelButton();
    bt_right->SetPosition(0,0,100,100);
    bt_right->SetImageSrc(g_rightAbsolutePath,g_rightAbsolutePath);
    bt_right->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_right->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_right->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_right->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_right_two = new UILabelButton();
    bt_right_two->SetPosition(0,0,100,100);
    bt_right_two->SetVisible(false);

    bt_left_three = new UILabelButton();
    bt_left_three->SetPosition(0,0,100,100);
    bt_left_three->SetVisible(false);

    bt_left_down = new UILabelButton();
    bt_left_down->SetPosition(0,0,100,100);
    bt_left_down->SetImageSrc(g_left_downAbsolutePath,g_left_downAbsolutePath);
    bt_left_down->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_left_down->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_left_down->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_left_down->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_down = new UILabelButton();
    bt_down->SetPosition(0,0,100,100);
    bt_down->SetImageSrc(g_downAbsolutePath,g_downAbsolutePath);
    bt_down->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_down->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_down->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_down->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_right_down = new UILabelButton();
    bt_right_down->SetPosition(0,0,100,100);
    bt_right_down->SetImageSrc(g_right_downAbsolutePath,g_right_downAbsolutePath);
    bt_right_down->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::White().full,UIButton::RELEASED);
    bt_right_down->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::RELEASED);
    bt_right_down->SetStyleForState(STYLE_BACKGROUND_COLOR,Color::Red().full,UIButton::UIButton::PRESSED);
    bt_right_down->SetStyleForState(STYLE_BORDER_RADIUS,0,UIButton::UIButton::PRESSED);

    bt_right_three = new UILabelButton();
    bt_right_three->SetPosition(0,0,100,100);
    bt_right_three->SetVisible(false);

    gridlayout->Add(bt_left_one);
    gridlayout->Add(bt_left_up);
    gridlayout->Add(bt_up);
    gridlayout->Add(bt_right_up);
    gridlayout->Add(bt_right_one);
    gridlayout->Add(bt_left_two);
    gridlayout->Add(bt_left);
    gridlayout->Add(bt_stop);
    gridlayout->Add(bt_right);
    gridlayout->Add(bt_right_two);
    gridlayout->Add(bt_left_three);
    gridlayout->Add(bt_left_down);
    gridlayout->Add(bt_down);
    gridlayout->Add(bt_right_down);
    gridlayout->Add(bt_right_three);
    gridlayout->LayoutChildren();  

大家可以看到这里我其实写了一个很挫的代码,为了布局而用了15个按钮,然后把左右两边给隐藏掉,其实写完之后,回顾的时候,才发现根本不需要这么做,根据现有的布局代码完全可以直接实现。这里我想提一下就是为了实现按钮的点击效果我在源码中找了好久,才测试出了一个比较好用的API:SetStyleForState

2.3.2 设置滑动回调类

首先这个类的原型是:void SetOnSwipeListener(OnSwipeListener& onSwipeListener)
由于之前C++只是拿QT写过一些界面,只接触传函数的,第一次接触这种传类的,所以一开始还是很蒙蔽的。
下面来看具体实现的细节:

class mySwipeListener : public UISwipeView::OnSwipeListener{
public: 
    mySwipeListener(UISwipeView* swipe,UILabel* label):
    swipe_(swipe),label_(label){};
    ~mySwipeListener() {};
    virtual void OnSwipe(UISwipeView &view) override
    {
        char buf[10] = {0};
        // sprintf_s(buf,sizeof(buf),".%d.",swipe_->GetCurrentPage() + 1);
        switch(swipe_->GetCurrentPage())
        {
            case 0:label_->SetText("当前模式:基础模式");break;
            case 1:label_->SetText("当前模式:第二种模式");break;
            case 2:label_->SetText("当前模式:第三种模式");break;
            default:
                label_->SetText("Error");
        }
    }
private:
    UISwipeView* swipe_ { nullptr };
    UILabel* label_ { nullptr };
};
    swipeListener = new mySwipeListener(swipe,label_remote_state);
    swipe->SetOnSwipeListener(swipeListener);

大家可以看到这种实现是:先继承参数中的那个类实现一个类,在类中去实现它的纯虚函数,这个函数刚好是我们需要实现业务逻辑的。

3.总结

源码部分就说完了,我在附件中会上传完整的源码包和hap包。目前搞这块儿确实资料很少,不过有源码,有什么需要就去源码中去搞.....

这里我算是做了第一步:在3516上写了一个遥控器,接下来就得去思考如何去连接3861智能小车车了。未完待续......

下载附件(包含源码包+hap包)

作者:Mr_qzk

想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这