3516遙控3861智能小車系列(一)C++開發界面應用


目錄:
1.harmonyos的設備開發的圖形圖像子系統
2.開始正式該應用的實現過程
3.總結
下載附件(包含源碼包+hap包)

 

老規矩先上該應用的演示視頻:https://harmonyos.51cto.com/show/3006

 

首先立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/就存放了源碼中的圖形模塊,各位大佬可以盡情去相關模塊源碼中遨游,然后能給我點兒指導也是極好的。

在這里我們先整理一下,目前已經開放的,包括源碼中已經有的圖形模塊可以分為兩部分一部分是容器類組件,一部分是普通組件,其中容器類組件有如下圖
普通類組件如下圖:

#2020征文-開發板#3516遙控3861智能小車系列(一)C++開發界面應用容器類組件:

#2020征文-開發板#3516遙控3861智能小車系列(一)C++開發界面應用

另外據我目前已有的探索結論是:一個主界面有一個RootView,使用GetWindowRootView來獲得,大家可以把它看成一個界面中最大的容器類組件,然后大家就是把界面相關的容器類組件,普通類組件往上堆就可以。當然別的多界面的實現方式應該不同。

2.開始正式該應用的實現過程:

#2020征文-開發板#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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM