top label word是什么意思_为什么GuiLite是最简单的GUI库

介绍

本文将向您展示GuiLite如何工作,架构是什么样的,然后您将了解为什么GuiLite是最小和最简单的GUI库。

快速回答:

  1. 只需5,000行C ++代码
  2. 只使用基本的C ++特性(类,虚函数),没有复杂的语法
  3. 所有渲染都基于draw_pixel,没有算法
  4. 完整文档和小型现场演示供参考

背景

  • GuiLite是一个具有5000行C ++代码的准系统GUI框架,它可以在所有平台上运行(例如,iOS,Android,Linux,Windows,macOS,Docker和带或不带OS的MCU)。
  • GuiLite是可嵌入的,它在其他UI框架内运行(例如,Qt,MFC,Winform,Cocoa)。您可以同时使用GuiLite功能和主机UI功能。
  • GuiLite独立于OS和图形库呈现UI
  • GuiLite可以使用多种语言(例如,Swift,Java,C#,Golang)。

以下是一些演示:

37656325c3b3e0c7612c8c642881995f.png

136902ed7cccdf07704ce33c13d9d6a6.png

45f24495238a408842153f69c3554a78.png

GuiLite做什么?

GuiLite只做两件事:小部件管理和渲染。

小部件管理包括:

  • 添加/删除GUI元素(例如:按钮,标签,对话框),设置标题和位置
  • 调度/响应输入消息:通过分析,来自消息的位置信息,GuiLite将找到应该响应的小部件,以及呼叫响应功能(例如on_mouse_clickon_keyboard_click
  • 调度/响应客户消息:通过分析消息的ID,GuiLite将找到响应函数,并调用它(例如on_timeron_custmer_refresh

渲染包括:

  • 绘制像素,直线,矩形
  • 设置框架图层:在绘图时,应输入框架图层索引以使图形位于特定图层
  • 更新帧图层:当帧图层更改时(例如:打开/关闭对话框),GuiLite将确定应在屏幕上显示哪个帧图像素

注意:渲染不依赖于窗口小部件管理。在某些情况下,您可以在GUI系统中直接渲染行/文本/位图而不使用任何小部件。例如:有限的资源MCU平台。

如何自定义/扩展GuiLite?

为了使GuiLite简单明了,GuiLite只提供基本的小部件(例如:按钮,标签,键盘,spinx等)实现。如果你想在小部件上做更多的事情,你可以这样做:

  • 直接在GuiLite中更新小部件代码
  • 添加新的窗口小部件文件,并通过引用GuiLite窗口小部件代码实现新的窗口小部件。

如果你想扩展绘图方法(例如,绘制圆/日蚀等),你可以直接在surface.cpp中添加你的方法。

怎么渲染?见功能draw_xxx()surface.cppword.cppbitmap.cpp

代码介绍

核心文件夹:

  • 为所有平台实现消息调度/响应,多帧层管理和呈现
  • Windows / Linux / Android / iOS / macOS上的适配器GuiLite或适配器文件夹中的无操作系统

小部件文件夹:

  • 这是控制器(例如,按钮,标签,键盘)和容器(例如,视图,对话框,翻页)的代码; 您可以通过修改此代码来重绘自己的小部件。
  • 这里是消息转换的代码(例如,手指按下/释放),它将手指按下/释放消息传递给已被触摸的小部件,并且如果定义则调用回调函数。

小部件管理

窗口小部件包括buttonspinboxlabelkeyboarddialogview; GuiLite将按功能链接所有小部件:connect,然后GuiLite将很容易地快速查找/添加/删除任何小部件。所有的连接看起来像一棵树。

例如:当您单击按钮时,设备获取您的手指位置(x,y)将发送树的根,GuiLite将通过比较位置信息找到您单击的按钮,然后调用响应函数(例如,重绘按钮/更改按钮状态)。

如何创建小部件?

所有小部件都源自class c_wnd。当实例化类时,将创建窗口小部件,此时,窗口小部件仍然单独,与UI系统无关,无法响应任何用户操作。

如何链接/取消链接小部件

通过使用“ connect()”函数,我们可以将此窗口小部件链接到窗口小部件树,然后窗口小部件可以响应用户触摸/键盘操作。

int c_wnd::connect(c_wnd *parent, unsigned short resource_id, const char* str,
           short x, short y, short width, short height, WND_TREE* p_child_tree )
{
    if(0 == resource_id)
    {
        ASSERT(FALSE);
        return -1;
    }

    m_resource_id = resource_id;
    m_parent  = parent;
    m_status = STATUS_NORMAL;

    if (parent)
    {
        m_z_order = parent->m_z_order;
        m_surface = parent->m_surface;
    }
    if(NULL == m_surface)
    {
        ASSERT(FALSE);
        return -2;
    }

    /* (cs.x = x * 1024 / 768) for 1027*768=>800*600 quickly*/
    m_wnd_rect.m_left    = x;
    m_wnd_rect.m_top    = y;
    m_wnd_rect.m_right    = (x + width - 1);
    m_wnd_rect.m_bottom = (y + height - 1);

    c_rect rect;
    get_screen_rect(rect);
    ASSERT(m_surface->is_valid(rect));

    pre_create_wnd();
    set_str(str);

    if ( 0 != parent )
    {
        parent->add_child_2_tail(this);
    }

    if (load_child_wnd(p_child_tree) >= 0)
    {
        load_cmd_msg();
        on_init_children();
    }
    return 0;
}

通过使用“ disconnect()”功能,从UI系统中取消链接此小组件。然后小部件仍然存在于内存中,但不再响应用户触摸/键盘操作。

void c_wnd::disconnect()
{
    if (0 == m_resource_id)
    {
        return;
    }

    if (NULL != m_top_child)
    {
        c_wnd *child = m_top_child;
        c_wnd *next_child = NULL;

        while (child)
        {
            next_child = child->m_next_sibling;
            child->disconnect();
            child = next_child;
        }
    }

    if (0 != m_parent)
    {
        m_parent->unlink_child(this);
    }
    m_focus_child = 0;
    m_resource_id = 0;
}

渲染

渲染包括渲染方法和图形管理。

  • 所有渲染方法都基于draw_pixel()功能
  • 到目前为止,GuiLite支持3个帧图层,可以处理3层重叠场景
void c_surface::draw_pixel(int x, int y, unsigned int rgb, unsigned int z_order)
{
    if (x >= m_width || y >= m_height || x < 0 || y < 0)
    {
        return;
    }
    if (z_order > m_max_zorder)
    {
        ASSERT(FALSE);
        return;
    }
    rgb = GL_ROUND_RGB_32(rgb);
    if (z_order == m_max_zorder)
    {
        return draw_pixel_on_fb(x, y, rgb);
    }

    if (z_order > m_top_zorder)
    {
        m_top_zorder = (Z_ORDER_LEVEL)z_order;
    }

    if (0 == m_frame_layers[z_order].rect.PtInRect(x, y))
    {
        ASSERT(FALSE);
        return;
    }
    ((unsigned short*)(m_frame_layers[z_order].fb))[x + y * m_width] = GL_RGB_32_to_16(rgb);

    if (z_order == m_top_zorder)
    {
        return draw_pixel_on_fb(x, y, rgb);
    }

    bool is_covered = false;
    for (int tmp_z_order = Z_ORDER_LEVEL_MAX - 1; tmp_z_order > z_order; tmp_z_order--)
    {
        if (TRUE == m_frame_layers[tmp_z_order].rect.PtInRect(x, y))
        {
            is_covered = true;
            break;
        }
    }

    if (!is_covered)
    {
        draw_pixel_on_fb(x, y, rgb);
    }
}
int c_surface::set_frame_layer(c_rect& rect, unsigned int z_order)
{
    if (rect == m_frame_layers[z_order].rect)
    {
        return 0;
    }
    if (rect.m_left < 0 || rect.m_left >= m_width ||
        rect.m_right < 0 || rect.m_right >= m_width ||
        rect.m_top < 0 || rect.m_top >= m_height ||
        rect.m_bottom < 0 || rect.m_bottom >=m_height)
    {
        ASSERT(FALSE);
        return -1;
    }
    if (!(z_order > Z_ORDER_LEVEL_0 && z_order < Z_ORDER_LEVEL_MAX))
    {
        ASSERT(FALSE);
        return -2;
    }
    if (z_order < m_top_zorder)
    {
        ASSERT(FALSE);
        return -3;
    }
    m_top_zorder = (Z_ORDER_LEVEL)z_order;

    c_rect old_rect = m_frame_layers[z_order].rect;
    //Recover the lower layer
    int src_zorder = (Z_ORDER_LEVEL)(z_order - 1);
    int display_width = m_display->get_width();
    int display_height = m_display->get_height();

    for (int y = old_rect.m_top; y <= old_rect.m_bottom; y++)
    {
        for (int x = old_rect.m_left; x <= old_rect.m_right; x++)
        {
            if (!rect.PtInRect(x, y))
            {
                unsigned int rgb = ((unsigned short*)
                                   (m_frame_layers[src_zorder].fb))[x + y * m_width];
                draw_pixel_on_fb(x, y, GL_RGB_16_to_32(rgb));
            }
        }
    }

    m_frame_layers[z_order].rect = rect;
    if (rect.IsEmpty())
    {
        m_top_zorder = (Z_ORDER_LEVEL)(z_order - 1);
    }
    return 0;
}

渲染方法

  • 基本渲染功能: surface_cpp.cpp::draw_xxx()
  • 位图渲染功能: bitmap.cpp::draw_bitmap_xxx()
  • 为了获得GPU优势,您可以draw_xxx()使用GPU功能进行重构

图形层

ee6820129d9fdf11fb81e334547b13db.png
  • 显示层:该层用于物理显示设备,一个UI只有一个显示层
  • 表面层:一个显示层有许多表面层,一个表面层表示一个翻页
  • 框架层:一个表面层具有许多框架层,一个框架层表示Z方向上的一个层

我们来看看如何创建一个显示:

c_display::c_display(void* phy_fb, unsigned int display_width, unsigned int display_height,
                        unsigned int surface_width, unsigned int surface_height,
                        unsigned int color_bytes, unsigned int surface_cnt, 
                        EXTERNAL_GFX_OP* gfx_op)
{
    if (color_bytes != 2 && color_bytes != 4)
    {
        log_out("Support 16 bits, 32 bits color only!");
        ASSERT(FALSE);
    }

    m_width = display_width;
    m_height = display_height;
    m_color_bytes = color_bytes;
    m_phy_fb = phy_fb;
    m_phy_read_index = m_phy_write_index = 0;
    memset(m_surface_group, 0, sizeof(m_surface_group));
    m_surface_cnt = surface_cnt;
    ASSERT(m_surface_cnt <= SURFACE_CNT_MAX);
    
    for (int i = 0; i < m_surface_cnt; i++)
    {
        m_surface_group[i] = phy_fb ? new c_surface
            (this, surface_width, surface_height, color_bytes) : 
            new c_surface_no_fb(this, surface_width, surface_height, color_bytes, gfx_op);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值