Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
RTGUI教程之三 -- workbench 下
发布于 2009-12-07 10:09:54 浏览:3290
订阅该版
============================= RTGUI教程之三 -- workbench 下 ============================= workbench下这一篇实际上讨论的是workbench上的view(视图)。 ---- 视图 ---- 如上节描述: 视图 -- 可以类比下,工作台好比自己的办公桌,桌子上满满的铺上了一张地图,占据了桌面的所有面积。但是,如何换一张地图呢?所以这里有了视图的概念,桌面上的地图可以一张张换,当然了,也可以只是一张。 视图实际上让工作台上有多重显示的能力,只需要把它一个个切换即可。而针对于显示面积比较小的液晶,窗口都不必要了,直接用视图代替: 显示消息对话框时,切换成相应的视图进行消息提示等。 如果是面向内存比较吃紧的嵌入式系统,也建议多使用视图,因为创建一个视图的开销要远远的小于创建窗口的开销,而且视图是GUI服务端不可见的(GUI服务端可见的是一个个的workbench,每个workbench又绑定到独立的线程上)。视图也可以看成是PC上的标签页,只是不相同的是RTGUI的视图少了标签页的按钮(或许以后会加上:-))。 view也是RTGUI里一类控件,继承于容器控件,它能够包含多个子控件等。既然视图是可以做为窗口的替代品,那么它就必须具备某些品质: 例如PC上的文件对话框,当父窗口需要打开一个文件时,通常会: ```void MainFrm::OnFileOpen() { /* 创建对话框 */ FileDiag diag(parent); /* 显示对话框 */ if (diag.ShowModal() == OK) { char* fn = diag.GetFileName(); /* 相应的文件处理操作 */ } }``` 这个其中隐含着: 文件对话框是基于父窗口的, 文件对话框等待用户交互,并取得最终的选择, 父窗口应该在ShowModal()上等待用户的输入,只有当文件对话框有结果时才继续往下运行,然后当获得文件名时进行相应的操作。 这类操作在GUI上叫做:模式对话框显示,以下的是wikipedia的解释: In user interface design, a modal window is a child window that requires the user to interact with it before they can return to operating the parent application, thus preventing the workflow on the application main window. Modal windows are often called heavy windows or modal dialogs because the window is often used to display a dialog box. ----------------------- RTGUI里的Modal View使用 ----------------------- 在RTGUI里,view创建时并不需要指定是否创建成modal视图,而是在显示时: rtgui_modal_code_t rtgui_view_show(rtgui_view_t* view, rt_bool_t is_modal); 参数is_modal指示出是否是modal的视图,如果是RT_TRUE,那么将显示一个modal模式的视图,并且这个函数直到用户选择了结果才会返回。 这个函数的返回值rtgui_modal_code_t的类型,目前只支持两种: RTGUI_MODAL_OK RTGUI_MODAL_CANCEL 而具体返回的值是由view的实现代码决定的,例如在view的事件处理函数中,当收到用户的键盘输入(RTGUIK_RETURN),它调用函数: void rtgui_view_end_modal(rtgui_view_t* view, rtgui_modal_code_t modal_code); 设置modal_code为RTGUI_MODAL_OK,这样就会返回RTGUI_MODAL_OK的值。 --------------------- Radio中Modal View示例 --------------------- 下面解析了Radio工程中使用Modal View的示例,完整的代码可以从Radio工程中获得。 player_ui.c的function_filelist函数: ```/* * 这个函数是挂接在功能列表里 struct list_item function_list[], * 被功能视图所使用,从而形成一个类似菜单的功能 */ void function_filelist(void* parameter) { rtgui_rect_t rect; filelist_view_t *view; /* 获得父workbench的矩形框信息 */ rtgui_widget_get_rect(RTGUI_WIDGET(workbench), &rect); /* 创建一个文件列表视图 */ view = filelist_view_create(workbench, "/", "*.*", &rect); if (view != RT_NULL) { /* 采用modal模式显示这个视图,这个函数只有在用户有相应交互的时候才返回 */ if (rtgui_view_show(RTGUI_VIEW(view), RT_TRUE) == RTGUI_MODAL_OK) { char fn[64]; /* * filelist视图返回时提供了当前目录,当前文件名的信息,所以这里根据 * 它们取得相应的文件名 */ rt_snprintf(fn, 64, "%s/%s", view->current_directory, view->items[view->current_item].name); /* mp3文件的处理 */ if (strstr(view->items[view->current_item].name , ".mp3") != RT_NULL || strstr(view->items[view->current_item].name , ".MP3") != RT_NULL) { /* clear old play list */ play_list_clear(); play_list_append(fn); player_mode = PLAYER_PLAY_FILE; next_step = PLAYER_STEP_STOP; play_mp3_file(play_list_start()); } /* m3u文件的处理 */ else if (strstr(view->items[view->current_item].name , ".m3u") != RT_NULL || strstr(view->items[view->current_item].name , ".M3U") != RT_NULL) { /* read all of music filename to a list */ int fd; char line[64]; fd = open(fn, O_RDONLY, 0); if (fd >= 0) { rt_uint32_t length; length = read_line(fd, line, sizeof(line)); if (strcmp(line, "#EXTM3U") == 0) { /* clear old play list */ play_list_clear(); do { length = read_line(fd, line, sizeof(line)); if (length > 0) { if (line[0] != '/') { rt_snprintf(fn, sizeof(fn), "%s/%s", view->current_directory, line); play_list_append(fn); } else play_list_append(line); } } while (length > 0); } close(fd); if (play_list_items() > 0) { player_mode = PLAYER_PLAY_FILE; next_step = PLAYER_STEP_NEXT; play_mp3_file(play_list_start()); } } } /* wav文件的处理 */ else if (strstr(view->items[view->current_item].name , ".wav") != RT_NULL || strstr(view->items[view->current_item].name , ".WAV") != RT_NULL) { } } /* 注意:从show_modal状态返回,视图并没消失,需要手动的删除这个视图以释放相应的内存 */ filelist_view_destroy(view); } return; } ``` filelist视图中和modal模式密切相关的代码:(注:filelist视图是一个全新的视图,从view继承而来) /* fileist.c文件 filelist视图事件处理函数 */ ```rt_bool_t filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) { struct filelist_view* view = RT_NULL; /* 这个是filelist视图,先把widget转换成filelist类型的结构 */ view = FILELIST_VIEW(widget); switch (event->type) { /* 重绘事件 */ case RTGUI_EVENT_PAINT: filelist_view_ondraw(view); return RT_FALSE; /* 更改大小事件 */ case RTGUI_EVENT_RESIZE: { struct rtgui_event_resize* resize; resize = (struct rtgui_event_resize*)event; /* recalculate page items */ if (file_image != RT_NULL) view->page_items = resize->h / (1 + rtgui_theme_get_selected_height()); else view->page_items = resize->h / (2 + 14); } break; /* 键盘按键输入事件 */ case RTGUI_EVENT_KBD: { struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; if (ekbd->type == RTGUI_KEYDOWN) /* 当是按键按下事件时 */ { rt_uint16_t old_item; old_item = view->current_item; switch (ekbd->key) { case RTGUIK_UP: /* 对UP方向键处理 */ if (view->current_item > 0) view->current_item --; filelist_view_update_current(view, old_item); return RT_FALSE; case RTGUIK_DOWN: /* 对DOWN方向键处理 */ if (view->current_item < view->items_count - 1) view->current_item ++; filelist_view_update_current(view, old_item); return RT_FALSE; case RTGUIK_LEFT: /* 对LEFT方向键处理 */ if (view->current_item - view->page_items >= 0) view->current_item -= view->page_items; filelist_view_update_current(view, old_item); return RT_FALSE; case RTGUIK_RIGHT: /* 对RIGHT方向键处理 */ if (view->current_item + view->page_items < view->items_count - 1) view->current_item += view->page_items; filelist_view_update_current(view, old_item); return RT_FALSE; case RTGUIK_RETURN: /* 对RETURN方向键处理 */ if (view->items[view->current_item].type == FITEM_DIR) { char new_path[64]; /* 如果当前项是目录 */ if (strcmp(view->items[view->current_item].name, ".") == 0) return RT_FALSE; if (strcmp(view->items[view->current_item].name, "..") == 0) { /* 父目录的处理 */ char *ptr; ptr = strrchr(view->current_directory, PATH_SEPARATOR); if (ptr == RT_NULL) return RT_FALSE; if (ptr == &(view->current_directory[0])) { /* it's root directory */ new_path[0] = PATH_SEPARATOR; new_path[1] = ' '; } else { strncpy(new_path, view->current_directory, ptr - view->current_directory + 1); new_path[ptr - view->current_directory] = ' '; } } else if (view->current_item == 0 && (view->current_directory[0] == '/') && (view->current_directory[1] == ' ')) { /* 如果是根目录,并且是第0个项(即显示的是 "退出文件浏览") */ if (RTGUI_VIEW(view)->modal_show == RT_TRUE) { /* 如果是modal模式显示,置modal返回值是RTGUI_MODAL_CANCEL */ rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_CANCEL); } else { /* 如果不是modal模式显示,直接删除这个视图 */ filelist_view_destroy(view); } return RT_FALSE; } else { /* 新目录的处理(进入这个目录) */ if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR) sprintf(new_path, "%s%c%s",view->current_directory, PATH_SEPARATOR, view->items[view->current_item].name); else sprintf(new_path, "%s%s",view->current_directory, view->items[view->current_item].name); } filelist_view_set_directory(view, new_path); } else { /* 是在文件上进行RETURN按键,并且是modal模式显示 */ if (RTGUI_VIEW(view)->modal_show == RT_TRUE) { /* 设置返回值为RTGUI_MODAL_OK */ rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK); } } return RT_FALSE; default: break; } } } return RT_FALSE; } /* 不是这个view感兴趣的时间,直接调用父类进行处理 */ return rtgui_view_event_handler(widget, event); } ```
查看更多
1
个回答
默认排序
按发布时间排序
撰写答案
登录
注册新账号
关注者
0
被浏览
3.3k
关于作者
bernard
这家伙很懒,什么也没写!
提问
414
回答
5940
被采纳
76
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
7
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
3
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部