本文將通過實現一個點擊切換進度的電量指示燈組件和exampleGUI組件庫介紹如何基于TinyPiXOS開發新組件。主要內容包括組件開發規范、自定義組件開發和組件庫開發三部分。
組件開發規范
命名規范
采用tp
開頭命名組件類,名稱具備易讀性。
目錄規范
- 頭文件放置
include/SingleGUI/widgets/
- 源文件放置
src/SingleGUI/widgets/
代碼結構(示例)
使用PIMPL
(Pointer to Implementation)設計規范,隱藏實現細節,降低編譯依賴性和增強代碼穩定性?。
使用TP_DEF_VOID_TYPE_VAR
宏聲明管理指針;所有成員變量或函數實現細節封裝在cpp中。
tpChildWidget
作為所有組件的基類,自定義組件必須繼承于tpChildWidget類并包含其頭文件。
#include "tpChildWidget.h"
class testLight : public tpChildWidget
{};
示例組件開發
組件介紹:實現一個點擊切換進度的電量指示燈。
實現步驟
創建自定義組件類testLight
創建testLight.cpp
和testLight.h
文件
組件類需繼承于tpChildWidget
#ifndef __TEST_LIGHT_H
#define __TEST_LIGHT_H#include "tpChildWidget.h"
#include "tpEvent.h"class testLight : public tpChildWidget
{
public:testLight(tpChildWidget *parent);virtual ~testLight();
};#endif
定義電量最大格數和當前顯示格數變量
int maxCount_;
int count_;
重寫onPaintEvent事件,根據電量格數繪制效果
- 獲取繪制畫筆
tpCanvas* painter = event->canvas();
- 繪制底色
painter->box(0, 0, width(), height(), _RGB(255, 255, 255));
- 根據最大格數計算每個格子的寬度
int spacing = 3;
int singleWidth = (width() - (maxCount_ + 1) * spacing) / maxCount_;
- 根據當前電量繪制電量格子
for (int i = 0; i < count_; ++i)
{int drawX = spacing + i * (singleWidth + spacing);painter->box(drawX, spacing, drawX + singleWidth, height() - spacing, _RGB(128, 255, 128));
}
重寫 onMousePressEvent 捕獲鼠標按下事件,獲取鼠標點擊狀態
bool testLight::onMousePressEvent(tpMouseEvent *event)
{tpChildWidget::onMousePressEvent(event);count_++;if (count_ > maxCount_)count_ = 0;return true;
}
組件測試(使用組件)
testLight* light = new testLight(this);
testButton_->setSize(200, 50);
testButton_->move(150, 300);
演示效果
初始化效果
點擊組件,增加顏色塊
完整源碼
頭文件:testLight.h
#ifndef __TEST_LIGHT_H
#define __TEST_LIGHT_H#include "tpChildWidget.h"
#include "tpEvent.h"class testLight : public tpChildWidget
{
public:testLight(tpChildWidget *parent);virtual ~testLight();public:virtual bool onMousePressEvent(tpMouseEvent *event) override;virtual bool onPaintEvent(tpObjectPaintEvent *event) override;private:int maxCount_;int count_;
};#endif
源碼:testLight.cpp
#include "testLight.h"
#include "tpCanvas.h"testLight::testLight(tpChildWidget *parent): tpChildWidget(parent), maxCount_(4), count_(0)
{
}testLight::~testLight()
{
}bool testLight::onMousePressEvent(tpMouseEvent *event)
{tpChildWidget::onMousePressEvent(event);count_++;if (count_ > maxCount_)count_ = 0;return true;
}bool testLight::onPaintEvent(tpObjectPaintEvent *event)
{tpChildWidget::onPaintEvent(event);tpCanvas *painter = event->canvas();painter->box(0, 0, width(), height(), _RGB(255, 255, 255));int spacing = 3;int singleWidth = (width() - (maxCount_ + 1) * spacing) / maxCount_;for (int i = 0; i < count_; ++i){int drawX = spacing + i * (singleWidth + spacing);painter->box(drawX, spacing, drawX + singleWidth, height() - spacing, _RGB(128, 255, 128));}return true;
}
組件庫介紹
當業務需求實現一整套統一樣式風格的GUI樣式庫時,可以使用組件庫的形式對相同樣式風格的組件進行統一管理,方便后期擴展及維護。未來tinyPiXOS會提供各種樣式風格的組件庫,并以當前規范進行發布。
本節將創建一個名為exampleGUI的組件庫,同時對testLight組件進行改造,將其加入exampleGUI組件庫。
目錄結構說明
組件庫開發需要遵循目錄結構規范,將組件庫的頭文件、源碼文件、構建文件等分類放入指定文件夾。并且需要創建FrameworkGlobal.h
放置組件庫全局定義,及命名空間聲明。目錄結構規范如下:
tinyPiXCore/
└─ PiXGUIFramework/├─ exampleGUI/│ ├─ CMakeList.txt│ └─ CMakePresets.json└─ src/├─ include/│ └─ GUIFramework/│ └─ exampleGUI/│ └─ widgets/│ └─ testLight.h└─ src/└─ GUIFramework/└─ exampleGUI/└─ widgets/└─ testLight.cpp
定義框架命名空間
編輯FrameworkGlobal.h
#ifndef _EXAMPLE_GUI_GLOBAL_H
#define _EXAMPLE_GUI_GLOBAL_H#define EXAMPLE_GUI_NAMESPACE_BEGIN namespace exampleGUI {
#define EXAMPLE_GUI_NAMESPACE_END }#endif
重構testLight類
使用PIMPL隱藏設計實現
這里我們將已經開發好的點擊切換進度的電量指示燈組件加入exampleGUI組件庫。
重構頭文件:testLigh.h
#ifndef __TEST_LIGHT_H
#define __TEST_LIGHT_H#include "tpChildWidget.h"
#include "tpEvent.h"
#include "FrameworkGlobal.h"EXAMPLE_GUI_NAMESPACE_BEGINTP_DEF_VOID_TYPE_VAR(ItestLightData);
class testLight : public tpChildWidget
{
public:testLight(tpChildWidget *parent);virtual ~testLight();public:virtual bool onMousePressEvent(tpMouseEvent *event) override;virtual bool onPaintEvent(tpObjectPaintEvent *event) override;private:ItestLightData *data_;
};EXAMPLE_GUI_NAMESPACE_END#endif
重構源代碼:testLigh.cpp
#include "testLight.h"
#include "tpCanvas.h"EXAMPLE_GUI_NAMESPACE_BEGINstruct testLightData
{int maxCount_;int count_;testLightData() : maxCount_(0), count_(0){}
};testLight::testLight(tpChildWidget *parent): tpChildWidget(parent)
{testLightData *lightData = new testLightData();lightData->maxCount_ = 4;lightData->count_ = 0;data_ = lightData;
}testLight::~testLight()
{testLightData *lightData = static_cast<testLightData *>(data_);if (lightData){delete lightData;lightData = nullptr;data_ = nullptr;}
}bool testLight::onMousePressEvent(tpMouseEvent *event)
{tpChildWidget::onMousePressEvent(event);testLightData *lightData = static_cast<testLightData *>(data_);lightData->count_++;if (lightData->count_ > lightData->maxCount_)lightData->count_ = 0;return true;
}bool testLight::onPaintEvent(tpObjectPaintEvent *event)
{tpChildWidget::onPaintEvent(event);testLightData *lightData = static_cast<testLightData *>(data_);tpCanvas *painter = event->canvas();painter->box(0, 0, width(), height(), _RGB(255, 255, 255));int spacing = 3;int singleWidth = (width() - (lightData->maxCount_ + 1) * spacing) / lightData->maxCount_;for (int i = 0; i < lightData->count_; ++i){int drawX = spacing + i * (singleWidth + spacing);painter->box(drawX, spacing, drawX + singleWidth, height() - spacing, _RGB(128, 255, 128));}return true;
}EXAMPLE_GUI_NAMESPACE_END
測試使用(使用組件庫)
CMakeList引入exampleGUI頭文件目錄和引入動態庫引用
include_directories(/usr/include/tinyPiX/GUIFramework)
target_link_libraries(examplesApp exampleGUI)
為防止多個UI框架頭文件重復導致引用異常,請使用UI框架的父級目錄引入。
#include"exampleGUI/widgets/testLight.h"
使用方式同上一節自定義組件
注:需添加命名空間引入
exampleGUI::testLight* light = new exampleGUI::testLight(this);
testButton_->setSize(200, 50);
testButton_->move(150, 300);
TinyPiXOS開發者聯盟
?源碼級支持 + 真實項目:TinyPiXOS開發者聯盟招募中?。
開發資料
關注我們
官網網站
技術資料
視頻合集
感謝支持和關注,如果對項目感興趣,請點贊、收藏和轉發!