【STM32H7】第16章 ThreadX GUIX窗口局部刷新的实现

2021-01-06 18:08:25 浏览数 (1)

最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

第16章 ThreadX GUIX窗口局部刷新的实现

本章节为大家讲解GUIX窗口的局部或全局刷新的实现。这个功能用的到地方也比较多,比如2D图形的更新,音乐频谱的更新,2D图像的更新等场合都会用到这个功能。

16.1初学者重要提示

16.2 GUIX Studio设置窗口回调

16.3 GUIX窗口更新功能的实现

16.4 实验例程设计框架

16.5实验例程

16.6 总结

16.1 初学者重要提示

1、 务必看第11章学习GUIX Studio的使用方法和第12章学习GUIX Studio生成的代码移植到硬件平台的方法。

2、 本章也要用到第15章的定时器更新功能。

3、 窗口或控件的局部更新和全局更新:

  • 局部更新是通过函数gx_system_dirty_partial_add来实现。
  • 全部更新是通过函数gx_system_dirty_mark来实现。
  • 调用时直接在窗口事件回调函数的消息里面调用即可,通过这两个函数会触发窗口或者控件的Drawing Function函数执行。

4、 注意,本章的方法不仅适用于窗口,各种控件上也适用。

16.2 GUIX Studio设置窗口回调

GUIX Studio的设置方法与第11章一样,我们这里把控件的位置和大小做了调整,并为window窗口创建一个定时器。

新调整的界面效果如下:

16.2.1 窗口事件回调设置

下面我们为窗口控件设置一个Event Function,此功能是窗口的事件回调函数。在这个回调函数里面,大家可以处理各种事件。

这里为Event Function设置的回调函数名为_cbEventWindow0,然后就可以使用GUIX Studio生成新的代码。生成的代码移植到硬件平台的方法看第12章即可。

16.2.2 窗口绘制回调设置

下面我们为窗口设置一个Draw Function,此功能是窗口的绘制回调函数。在这个回调函数里面,大家可以实现各种2D绘制。

这里为Draw Function设置的回调函数名为_cbWindow0,然后就可以使用GUIX Studio生成新的代码。

16.3 GUIX窗口更新功能的实现

在GUIX Studio上设置好事件回调函数和绘制回调函数后,剩下就是在程序里面实现定时器更新2D绘制,这里把实现方法为大家做个说明。

16.3.1 窗口全局更新方法

窗口全局更新比较简单,调用函数gx_system_dirty_mark来标记窗口为dirty即可,这样就会触发GUIX执行绘制回调函数。

代码语言:javascript复制
#definegx_system_dirty_mark(a)     _gx_system_dirty_mark((GX_WIDGET *)a);
UINT _gx_system_dirty_mark(GX_WIDGET *widget);
  • 形参widget是大家要更新的窗口句柄。

16.3.2 窗口局部更新方法

窗口局部更新也比较容易实现,调用函数gx_system_dirty_partial_add来标记窗口为dirty,这样就会触发GUIX执行绘制回调函数。

代码语言:javascript复制
#define gx_system_dirty_partial_add(a, b)   _gxe_system_dirty_partial_add((GX_WIDGET *)a, b)
UINT  _gxe_system_dirty_partial_add(GX_WIDGET *widget, GX_RECTANGLE *dirty_area)

与全局更新不同的是局部更新可以设置想更新的区域,这样可以有效降低CPU和DMA2D的利用率。

  • 第1个参数是大家要更新的窗口句柄。
  • 第2个参数是要更新的区域。更新区域是GX_RECTANGLE类型结构体,此结构体定义了矩形区域。

16.3.3 窗口里界面更新框架

GUIX更新界面实现框架如下:

代码语言:javascript复制
/*
*********************************************************************************************************
*    函 数 名: _cbWindow0
*    功能说明: 窗口window的绘制回调函数
*    形    参: widget     窗口句柄 
*    返 回 值: 无
*********************************************************************************************************
*/
VOID _cbWindow0(GX_WINDOW *widget)
{
    /* 2D绘制部分 */
}

/*
*********************************************************************************************************
*    函 数 名: _cbEventWindow
*    功能说明: 窗口window的事件回调函数
*    形    参: widget     窗口句柄 
*             event_ptr  事件指针
*    返 回 值: 返回0表示成功
*********************************************************************************************************
*/
UINT _cbEventWindow(GX_WINDOW *widget, GX_EVENT *event_ptr)
{

    switch (event_ptr->gx_event_type)
    {
        /* 控件显示事件 */
        case GX_EVENT_SHOW:
/* 启动一个GUIX定时器 */
gx_system_timer_start((GX_WIDGET *)widget, GUI_ID_Timer0, 1, 10);
break;

        /* 定时器时间溢出事件*/
        case GX_EVENT_TIMER:
            if (event_ptr->gx_event_payload.gx_event_timer_id == GUI_ID_Timer0)
            {
                //gx_system_dirty_mark(widget);
                gx_system_dirty_partial_add(widget, &WinPartialDraw);
            }
            break;

        default:
            return gx_window_event_process(widget, event_ptr);
    }

    return 0;
}

实现思路如下:

  • 事件回调函数里面创建定时器,然后定时器消息GX_EVERNT_TIMER周期调用函数gx_system_dirty_mark或者gx_system_dirty_partial_add来触发窗口绘制回调函数的执行。
  • 绘制回调函数_cbWindow0里面可以绘制各种2D效果。

16.3.4 窗口里界面更新功能实例(重要)

实例代码如下,本章教程配套例子也是用的这个代码:

代码语言:javascript复制
GX_RECTANGLE WinPartialDraw =  {10, 170, 400, 230};

/*
*********************************************************************************************************
*    函 数 名: _cbWindow0
*    功能说明: 窗口window的绘制回调函数
*    形    参: widget     窗口句柄 
*    返 回 值: 无
*********************************************************************************************************
*/
VOID _cbWindow0(GX_WINDOW *widget)
{
    static uint32_t i = 0;
    GX_RECTANGLE drawto;  
    GX_CANVAS *mycanvas; 
    
    /* 默认的窗口绘制回调函数,即默认界面效果绘制 */
    gx_window_draw(widget);

    /* 定义一个矩形框,后续的2D绘制函数都是在这个矩形范围内绘制的 */
    gx_utility_rectangle_define(&drawto,
                                WinPartialDraw.gx_rectangle_left, 
                                WinPartialDraw.gx_rectangle_top,
                                WinPartialDraw.gx_rectangle_right, 
                                WinPartialDraw.gx_rectangle_bottom);
 
    /* 返回窗口对应的canvas画布 */
    gx_widget_canvas_get(widget, &mycanvas);
    
    /* 
      在指定的画布上启动绘图。此功能在内部被延迟绘图算法调用,GUIX在需要画布时自动执行更新。 
      但是允许应用程序绕过延期绘图算法并立即执行。
      首先调用gx_canvas_drawing_inititate在画布上绘画。
      然后调用所需的绘图函数,然后调用gx_canvas_drawing_complete即可。
    */
    gx_canvas_drawing_initiate(mycanvas, widget, &drawto);

    /* 设置笔刷画线的颜色值 */
    gx_context_raw_line_color_set(0xffff0000);

    /* 设置笔刷填充的颜色值 */   
    gx_context_raw_fill_color_set(0xff00ff00);

    /* 通过GX_BRUSH_SOLID_FILL使能圆圈,矩形,多边形等绘制为填充效果 */
    gx_context_brush_style_set(GX_BRUSH_SOLID_FILL);

    /* 设置笔刷线宽 */
    gx_context_brush_width_set(1);
 
    /* 绘制圆圈 */
    gx_canvas_circle_draw(50 (i  )00, 200, 25);

    /* 用于强制立即绘制,注意,务必和gx_canvas_drawing_initiate成对调用 */
    gx_canvas_drawing_complete(mycanvas, GX_TRUE);
}

/*
*********************************************************************************************************
*    函 数 名: _cbEventWindow
*    功能说明: 窗口window的事件回调函数
*    形    参: widget     窗口句柄 
*             event_ptr  事件指针
*    返 回 值: 返回0表示成功
*********************************************************************************************************
*/
UINT _cbEventWindow(GX_WINDOW *widget, GX_EVENT *event_ptr)
{

    switch (event_ptr->gx_event_type)
    {
        /* 控件显示事件 */
        case GX_EVENT_SHOW:
          
            /* 启动一个GUIX定时器 */
            gx_system_timer_start((GX_WIDGET *)widget, GUI_ID_Timer0, 1, 10);

            /* 默认事件处理 */
            gx_window_event_process(widget, event_ptr);
            break;

        /* 定时器时间溢出事件*/
        case GX_EVENT_TIMER:
            if (event_ptr->gx_event_payload.gx_event_timer_id == GUI_ID_Timer0)
            {
                //gx_system_dirty_mark(widget);
                gx_system_dirty_partial_add(widget, &WinPartialDraw);
            }
            break;

        default:
            return gx_window_event_process(widget, event_ptr);
    }

    return 0;
}
  • GX_RECTANGLE WinPartialDraw

定义要重绘的矩形区域。为了实现方便起见,绘制回调函数_cbWindow0设置的绘制区域(由函数gx_utility_rectangle_define定义)和函数gx_system_dirty_partial_add都是采用的这个区域。

  • _cbWindow0

窗口的绘制回调函数,此函数里面调用的各种函数在第13章有详细说明。

  • GX_EVENT_SHOW

窗口显示事件。当窗口显示时,会产生此消息,既可以附加到一个可见窗口,也可以通过函数gx_widget_show()。窗口(控件)绘制前会产生此消息。

  • GX_EVENT_TIMER

定时器周期性溢出事件。

此消息里面可以调用局部刷新函数gx_system_dirty_partial_add和全局刷新函数gx_system_dirty_mark。

针对这个实例,推荐大家设置不同的参数看效果,熟练掌握这些函数的用法,这样用起GUIX也得心应手。

16.4 实验例程设计框架

本章例程的重点是GUIX窗口更新的实现,任务中专门为窗口设置了Event Function事件回调函数和Draw Function绘制回调函数。

16.5 实验例程

(注,如果是电阻屏,需要做触摸校准,校准方法看本教程附件章节A)

配套例子:

本章节配套了如下两个例子供大家移植参考:

  • V7-2017_GUIX Window Update

GUIX Studio生成的代码在硬件平台实际运行的工程,含有GCC,IAR,MDK AC5和AC6四个版本工程。

  • V7-2018_GUIX Studio Window Update

GUIX Studio工程模板,设计界面后,生成的文件可直接添加到MDK,IAR和GCC软件平台使用。

实验目的:

  1. 本章主要学习GUIX的局部刷新功能。

实验内容:

  1. 共创建了如下几个任务,通过按下按键K1可以通过串口打印任务堆栈使用情况

App Task Start任务 :启动任务,这里用作BSP驱动包处理。

App Task MspPro任务 :消息处理,这里用作LED闪烁。

App Task UserIF任务 :按键消息处理。

App Task GUI任务 :GUI应用任务。

App Task STAT任务 :统计任务。

App Task IDLE任务 :空闲任务。

GUIX System Thread :GUI系统任务。

System Timer Thread任务:系统定时器任务。

实验效果:

GUIX Studio的界面设计如下:

串口打印任务执行情况:

IAR,MDK AC5和AC6工程可以串口打印任务执行情况:按开发板的按键K1可以打印,波特率 115200,数据位 8,奇偶校验位无,停止位 1:

Embedded Studio(GCC)平台的串口打印是通过其调试组件SEGGER RTT做的串口打印,速度也非常快,打印效果如下:

展示里面有乱码是因为Embedded Studio不支持中文。

16.6 总结

本章节主要为大家讲解了GUIX窗口局部刷新的实现,推荐大家设置不同的参数看效果,熟练掌握这些函数的用法。

0 人点赞