TinyUI

    TinyUI是本人在疫情期間開發的一套可移植的嵌入式UI庫,如果感興趣的人比較多將開源出來。

---------------------------------------------------------------------------------------------------------------------------------

    windows模擬器演示程序。
    下載地址:https://pan.baidu.com/s/1sLhGqH0GZKEFkALCWVHCAg
    提取碼: yooy

---------------------------------------------------------------------------------------------------------------------------------

 

    TinyUI是一套適用於嵌入式平臺開發的UI庫,具有比較完整的事件驅動系統,該UI庫使用方便簡單。

    目前基於低端嵌入式UI大多使用C語言進行開發或設計界面時需要計算UI組件/控件座標,無法提高產品開發效率,或大多數嵌入式開發人員自行涉及UI,大多設計都在中斷中顯示UI或處理業務邏輯。另外一個更重要的問題即是無法自適應不同尺寸的屏幕,每開發新的產品或更換屏幕時都需要大量的修改或重寫。

    本UI庫使用C++(C++ 11或以上版本)進行開發,其大多數UI組件/控件均參考主流平臺進行設計,如ListView、GridView、LinearLayout、Spinner、ScrollView、TabView、Dialog等UI組件基本設計與Android一致,並且這些UI組件/控件的使用方法均與Android APP開發一致;其中GridLayout的使用方法與WPF/UWP基本一致。

TinyUI主要特點:

    1. 提供LinearLayout和GridLayout等2種UI佈局,可自適應不同尺寸屏幕,並且可以佈局嵌套;

    2. UI組件/控件使用簡單,與主流平臺設計相似;

    3. 對於處理器是否集成LCD控制器均支持,並且如果內存夠大還可以支持雙緩存,可支持任意大小尺寸屏幕;

    4. 對無觸摸(但需要有按鍵),幾乎所有可獲得焦點的UI組件/控件均可綁定按鍵,當物理按鍵按下時UI組件/控件自動響應事件,而無需開發人員進行處理;

    5. 所有的UI組件/控件可用功能比較豐富,如: TextView提供多種對齊、跑馬方式,以及省略號結尾等;

    6. 移植簡單,底層驅動只需實現TinyUI定義的4個接口即可,如: LCD、按鍵、定時器、觸摸;

    7. TinyUI使用自定義字庫,矢量字體顯示使得文字細節非常豐富(把本模擬器截圖粘貼到windows自帶畫圖中,放大數倍即可看到字體細節),字體放大後的效果如下;

    8. TinyUI可移植目標平臺豐富;

    9. TinyUI使用UTF8編碼;

目前模擬器未使用鼠標鉤子,使用鉤子需要轉換座標:),有時鼠標擡起事件會丟失。TinyUI由本人/個人開發&測試,開發時間不足2個月,因此部分小UI組件/控件還未完成,同時會存在一定的BUG。

 

 

------------- TinyUI非常年輕,它的的發展需要大家的支持,您的支持將是我最大的動力。

 

如下貼出部分演示代碼:

AboutWindow.h


class AboutWindow : public TUIWindow, public TUIButtonListener
{
public:
    AboutWindow(TUIWindow* parent = nullptr);
    virtual ~AboutWindow();

    void onShow();
    void onClose();

    void onClick(TUIButton* view);

private:
    TUIGridLayout rootLayout; // 頂層內容視圖使用GridLayout
    TUIButton backButton; // 返回按鈕
};

 

AboutWindow.cpp

AboutWindow::AboutWindow(TUIWindow* parent)
    : TUIWindow(parent)
{
    setContentView(&this->rootLayout); // 設置GridLayout爲當前窗口的內容視圖

    this->rootLayout.setRowNumber(3); // 3行
    this->rootLayout.setColumnNumber(2); // 3列

    this->rootLayout.setRowHeight(0, 30); // 第1行高30
    this->rootLayout.setRowHeight(1, 30); // 第2行高30
    this->rootLayout.setRowHeight(2, TUILAYOUT_DIM::TUI_MATCH_REMAIN); // 第3行高佔滿剩餘空間

    this->rootLayout.setColumnWidth(0, 50); // 第1列寬50
    this->rootLayout.setColumnWidth(1, TUILAYOUT_DIM::TUI_MATCH_REMAIN); // 第2列佔滿剩餘空間

    this->backButton.setText(L"返回");
    this->backButton.setMargin(2, 0, 2, 0); // 設置按鈕外邊距(順序: 左->上->右->下)
    this->backButton.registerListener(this); // 當前窗口監聽backButton點擊事件
    this->backButton.bindKeycode(TUIVKCode::TUIVK_BACK); // backButton綁定回退鍵
    this->rootLayout.addView(&this->backButton, 0, 0); // backButton放到第0行,第0列
}

 

顯示AboutWindow:

aboutWindow.show();

 

 

移植

TinyUI本身並不需要使用者做大量的工作,除非你需要更高級的功能(需要提供一個軟中斷給TinyUI)。

 

移植的難易程度取決於你的驅動結構好壞。

 

注: 我的驅動是C寫的

 

1. 定時器接口移植

UITimer::UITimer(int32_t id)
{
    if (0 == id)
    {
        normal_timer = (timer_t *)device_driver_autowired(DDTYPE_TIMER, DDID_TIMER02);
		normal_timer->ops->open(TIMER_MILLISECOND, TIMER_CONTINUOUS);
    }
}

UITimer::~UITimer()
{

}

void UITimer::start(uint32_t millisecond)
{
    if (nullptr == normal_timer)
    {
        return;
    }

    normal_timer->ops->start(millisecond);
}

void UITimer::stop()
{
    if (nullptr == normal_timer)
    {
        return;
    }

    normal_timer->ops->close();
}


void UITimer::registerCallback(timeoutCallback callback)
{
    if (nullptr == normal_timer)
    {
        return;
    }

    normal_timer->ops->register_timeout_callback(callback);
}

 

2. LCD接口移植

UIDisplay::UIDisplay()
{
    ili9341 = (lcd_controller_t *)device_driver_autowired(DDTYPE_LCD_CONTROLLER, DDID_LCD_CONTROLLER_ILI9341);
    ili9341->ops->open();
}

UIDisplay::~UIDisplay()
{

}

bool UIDisplay::readPoint(int32_t x, int32_t y, color_t* color)
{
    uint16_t c = 0;
    ili9341->ops->read_point(x, y, &c);

    *color = c;

    return true;
}

void UIDisplay::drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color)
{
    ili9341->ops->draw_point(x, y, color);
}

void UIDisplay::drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color)
{
    ili9341->ops->draw_line(x1, y1, x2, y2, color);
}

void UIDisplay::drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer)
{
    ili9341->ops->draw_buffer(x, y, bufferWidth, bufferHeight, buffer);
}


void UIDisplay::clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color)
{
    ili9341->ops->clear(x, y, width, height, color);
}

uint8_t UIDisplay::getBPP()
{
    return ili9341->ops->get_bpp();
}

uint32_t UIDisplay::getScreenWidth()
{
    return ili9341->ops->get_width();
}

uint32_t UIDisplay::getScreenHeight()
{
    return ili9341->ops->get_height();
}

uint8_t* UIDisplay::getFB()
{
    //return g_FrameBuffer; // 不支持
    return nullptr;
}

void UIDisplay::submit(uint8_t* buffer)
{
    //ili9341->ops->draw_buffer(0, 0, 320, 240, g_FrameBuffer); // 不支持
}

 

3. TinyUI初始化及驅動

void initTinyUI()
{
    TUIInit(); // Tiny初始化

    UIDisplay *display = new UIDisplay();
    TUIRegisterFBInterface(display); // 註冊顯示接口

    UITimer *timer0 = new UITimer(0); // 實例化一個定時器給TinyUI使用
    TUIRegisterTimerInterface(0, timer0);

    string filePath = "1:font.tui"; // 字庫路徑
    TUIRegisterFontInterface(TUIFontRenderer::instance(), filePath.c_str()); // 註冊字體渲染器,TinyUI運行自定義

    MyLauncher* myLauncher = new MyLauncher(); // 定義自己的主界面
    TUIStartup(myLauncher); // 把自己的主界面註冊到TinyUI中
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章