Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
RTGUI的filelist_view控件
发布于 2013-02-25 11:50:54 浏览:4833
订阅该版
使用filelist_view控件的时候发现一点儿问题, 点击文件没有问题, 点击文件夹出错。跟踪调试了一下,发现一点儿问题: 1) 点击文件夹选项时,会创建并显示一个类似于popupmenu的窗口; 2)```static void rtgui_filelist_view_menu_pop(rtgui_widget_t *parent) { rtgui_win_t *menu; rtgui_listbox_t *listbox; rtgui_rect_t screen, rect = {0, 0, 140, 85}; rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen); rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL); menu = rtgui_win_create(RTGUI_WIN(rtgui_widget_get_toplevel(parent)), "Folder Menu", &rect, RTGUI_WIN_STYLE_DEFAULT); if (menu != RT_NULL) { /* set user data on menu window */ menu->user_data = (rt_uint32_t)parent; rtgui_win_set_ondeactivate(menu, rtgui_filelist_view_on_menu_deactivate); listbox = rtgui_listbox_create(items, sizeof(items) / sizeof(items[0]), &rect); rtgui_listbox_set_onitem(listbox, rtgui_filelist_view_on_folder_item); rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(listbox)); rtgui_listbox_set_current_item(listbox, 0); rtgui_win_show(menu, RT_TRUE); } }``` ```void rtgui_listbox_set_current_item(rtgui_listbox_t *box, int index) { RT_ASSERT(box != RT_NULL); if (index >= box->items_count) return; if (index != box->current_item) { int old_item; old_item = box->current_item; box->current_item = index; rtgui_listbox_update_current(box, old_item); } if (box->on_item) box->on_item(RTGUI_OBJECT(box), RT_NULL); }``` ```static rt_bool_t rtgui_filelist_view_on_folder_item(rtgui_object_t *object, struct rtgui_event *event) { rtgui_win_t *menu; rtgui_listbox_t *listbox; rtgui_filelist_view_t *view; listbox = RTGUI_LISTBOX(object); menu = RTGUI_WIN(rtgui_widget_get_toplevel(RTGUI_WIDGET(object))); view = RTGUI_FILELIST_VIEW(menu->user_data); /* hide window */ rtgui_win_hide(menu); switch (listbox->current_item) { case 0: { char *dir_ptr; /* destroy menu window */ rtgui_win_destroy(menu); dir_ptr = (char *) rtgui_malloc(256); rtgui_filelist_view_get_fullpath(view, dir_ptr, 256); rtgui_filelist_view_set_directory(view, dir_ptr); rtgui_free(dir_ptr); } break; case 1: /* destroy menu window */ rtgui_win_destroy(menu); break; default: /* destroy menu window */ rtgui_win_destroy(menu); break; } return RT_TRUE; }``` 设置listbox的current item时会直接调用该选项对应的处理函数,该函数会调用rtgui_win_destroy(menu),也就是说menu还没有显示就已经destroy了,于是出错。 我的修改方法有两个: 1)屏蔽掉 //if (box->on_item) // box->on_item(RTGUI_OBJECT(box), RT_NULL); 不过这样就修改了listbox控件的行为。 2)不弹出窗口,如果按下的是文件夹,直接进入下一级目录,刷新filelist_view。
查看更多
11
个回答
默认排序
按发布时间排序
prife
2013-02-25
这家伙很懒,什么也没写!
这个bug确实存在,在simulator里测试就发现了。 楼主能否给出patch或者diff文件?
grissiom
2013-02-28
这家伙很懒,什么也没写!
这个等到下一个版本改掉吧
softwind
2013-02-28
这家伙很懒,什么也没写!
按方法1)修改之后在RealTouch例程的基础上继续使用filelist_view控件, ``` static void on_sel_btn(struct rtgui_object* object, struct rtgui_event* event) { struct rtgui_win* win; struct rtgui_button *button; struct rtgui_rect screen, rect = {0, 0, 350, 250}; rtgui_filelist_view_t *view; rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen); rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL); win = rtgui_win_create(main_win, "filelist", &rect, TGUI_WIN_STYLE_DEFAULT | RTGUI_WIN_STYLE_DESTROY_ON_CLOSE); view = rtgui_filelist_view_create("/", "*.*", &rect); rtgui_container_add_child(RTGUI_CONTAINER(win), RTGUI_WIDGET(view)); rtgui_win_show(win, RT_TRUE); } ``` 在一个空的block_panel上创建一个按钮,上面的代码是按钮的处理函数,创建一个win,添加一个filelist_view,以模态的方式显示该窗口,对filelist_view进行操作;按文件夹选项会弹出一个模态的对话框(pop memu),按“打开文件夹”选项会出现hard fault, filelist_view控件相应的处理代码为: ``` static rt_bool_t rtgui_filelist_view_on_folder_item(rtgui_object_t *object, struct rtgui_event *event) { rtgui_win_t *menu; rtgui_listbox_t *listbox; rtgui_filelist_view_t *view; listbox = RTGUI_LISTBOX(object); menu = RTGUI_WIN(rtgui_widget_get_toplevel(RTGUI_WIDGET(object))); view = RTGUI_FILELIST_VIEW(menu->user_data); /* hide window */ rtgui_win_hide(menu); switch (listbox->current_item) { case 0: { char *dir_ptr; dir_ptr = (char *) rtgui_malloc(256); rtgui_filelist_view_get_fullpath(view, dir_ptr, 256); rtgui_filelist_view_set_directory(view, dir_ptr); rtgui_free(dir_ptr); /* destroy menu window */ rtgui_win_destroy(menu); } break; case 1: /* destroy menu window */ rtgui_win_destroy(menu); break; default: /* destroy menu window */ rtgui_win_destroy(menu); break; } return RT_TRUE; } ``` 其中第一个分支处的 ``` /* destroy menu window */ rtgui_win_destroy(menu) ``` 本来是在分支的开始调用的,也就是在dir_ptr = (char *) rtgui_malloc(256)之前调用的,不知为什么会出现hard fault错误;因为对整个rtgui消息的分发和处理过程没有概念,也不知要怎么调试;试着将rtgui_win_destroy(menu)放在rtgui_free(dir_ptr)之后调用,程序又可以正常运行了,不知是什么原因? 另外一个问题是,因为包含filelist_view的窗口创建的时候指定了RTGUI_WIN_STYLE_DESTROY_ON_CLOSE属性,按理说关闭窗口的时候会destroy子控件及窗口本身,可是我用list_mem()发现,窗口关闭后,会有“内存的泄漏”;而且在filelist_view中进入的目录深度不一样,“内存泄漏”的数量也不一样;试着在窗口中不添加filelist_view控件,添加其他的控件(均为动态创建的),比如说按钮之类的,窗口关闭后就不会出现“内存泄漏”。不知是什么原因?另外我直接运行RealTouch例程(以Module模式)中的filelist,然后在program list页面关闭应用程序(因为例程中的win没有关闭按钮,也没有RTGUI_WIN_STYLE_DESTROY_ON_CLOSE属性),就不存在“内存泄漏”的问题,实在是搞不明白。 说明: ``` win = rtgui_win_create(main_win, "filelist", &rect, RTGUI_WIN_STYLE_DEFAULT | RTGUI_WIN_STYLE_DESTROY_ON_CLOSE) ``` 中的main_win就是app_mgr_entry()中创建的主窗口。 PS: 1) “内存泄漏”加引号是因为可能是我的使用方法不正确。 2) rtgui中的thread,app,win完全没概念呀,很费劲儿。
softwind
2013-03-05
这家伙很懒,什么也没写!
关于filelist_view控件的问题,还是没有解决。我试着调试了一下代码,发现几个问题: 主要是windows的消息处理函数 ``` rt_bool_t rtgui_win_event_handler(struct rtgui_object *object, struct rtgui_event *event) { struct rtgui_win *win; RT_ASSERT(object != RT_NULL); RT_ASSERT(event != RT_NULL); win = RTGUI_WIN(object); switch (event->type) { ...... case RTGUI_EVENT_MOUSE_BUTTON: { rt_bool_t res = rtgui_container_dispatch_mouse_event(RTGUI_CONTAINER(win), (struct rtgui_event_mouse *)event); #ifndef RTGUI_USING_SMALL_SIZE if (RTGUI_WIDGET(object)->on_mouseclick != RT_NULL) { RTGUI_WIDGET(object)->on_mouseclick(object, event); } #endif /* check whether has widget which handled mouse event before. * * Note #1: that the widget should have already received mouse down * event and we should only feed the mouse up event to it here. * * Note #2: the widget is responsible to clean up * last_mevent_widget on mouse up event(but not overwrite other * widgets). If not, it will receive two mouse up events. */ if (((struct rtgui_event_mouse *)event)->button & RTGUI_MOUSE_BUTTON_UP && win->last_mevent_widget != RT_NULL) { RTGUI_OBJECT(win->last_mevent_widget)->event_handler( RTGUI_OBJECT(win->last_mevent_widget), event); /* clean last mouse event handled widget */ win->last_mevent_widget = RT_NULL; } return res; } ...... default: return rtgui_container_event_handler(object, event); } return RT_FALSE; } ``` 主要是RTGUI_EVENT_MOUSE_BUTTON消息的处理,该分支一开始就会调用 ``` rtgui_container_dispatch_mouse_event(...) ``` 将消息分发到子控件;而filelist_view点击文件夹后会弹出一个模态对话框(popmenu),其中的子控件listbox的消息响应函数如下: ``` static rt_bool_t rtgui_filelist_view_on_folder_item(rtgui_object_t *object, struct rtgui_event *event) { rtgui_win_t *menu; rtgui_listbox_t *listbox; rtgui_filelist_view_t *view; listbox = RTGUI_LISTBOX(object); menu = RTGUI_WIN(rtgui_widget_get_toplevel(RTGUI_WIDGET(object))); view = RTGUI_FILELIST_VIEW(menu->user_data); /* hide window */ rtgui_win_hiden(menu); switch (listbox->current_item) { case 0: { char *dir_ptr; /* destroy menu window */ rtgui_win_destroy(menu); dir_ptr = (char *) rtgui_malloc(256); rtgui_filelist_view_get_fullpath(view, dir_ptr, 256); rtgui_filelist_view_set_directory(view, dir_ptr); rtgui_free(dir_ptr); } break; case 1: /* destroy menu window */ rtgui_win_destroy(menu); break; default: /* destroy menu window */ rtgui_win_destroy(menu); break; } return RT_TRUE; } ``` 也就是说在一个模态窗口的子控件的消息响应函数中执行了rtgui_win_destroy()操作,当子控件的消息处理函数执行完回到windows的消息处理函数时(即函数rtgui_container_dispatch_mouse_event)返回时,该窗口对象已经释放了,之后不应该再对它执行操作,但现在的代码还有对它的操作,例如 ``` if (RTGUI_WIDGET(object)->on_mouseclick != RT_NULL) { RTGUI_WIDGET(object)->on_mouseclick(object, event); } ``` 程序执行到这里就会出错,因为RTGUI_WIDGET宏还是要针对object做一些操作,但object已经释放了。 之前版本的rtgui代码,windows控件针对RTGUI_EVENT_MOUSE_BUTTON消息的处理代码与现在的版本有些不同,相关代码如下: ``` case RTGUI_EVENT_MOUSE_BUTTON: /* check whether has widget which handled mouse event before */ if (win->last_mevent_widget != RT_NULL) { RTGUI_OBJECT(win->last_mevent_widget)->event_handler( RTGUI_OBJECT(win->last_mevent_widget), event); /* clean last mouse event handled widget */ win->last_mevent_widget = RT_NULL; } else if (rtgui_container_dispatch_mouse_event(RTGUI_CONTAINER(win), (struct rtgui_event_mouse *)event) == RT_FALSE) { #ifndef RTGUI_USING_SMALL_SIZE if (RTGUI_WIDGET(object)->on_mouseclick != RT_NULL) { return RTGUI_WIDGET(object)->on_mouseclick(object, event); } #endif } break ``` 当子控件的消息处理函数返回值为RT_TRUE时,不会执行 ``` #ifndef RTGUI_USING_SMALL_SIZE if (RTGUI_WIDGET(object)->on_mouseclick != RT_NULL) { return RTGUI_WIDGET(object)->on_mouseclick(object, event); } #endif ``` 处的操作,使得这一问题没有出现。 以上是我的理解,希望大家讨论,赐教。
grissiom
2013-03-06
这家伙很懒,什么也没写!
LS 提的问题很对~~ LSS 提的问题我近期会看看~~
nongxiaoming
2013-04-14
rt-thread大师兄
这个之前也发现了,有时还会直接死掉~
xdzy
2013-06-21
这家伙很懒,什么也没写!
不知道这个问题解决了没有,我用0.62版本也出现 打开文件夹 出现硬件异常的现象,追踪发现只要在rtgui_filelist_view_on_folder_item这个函数里面有内存操作动作如rt_snprintf(),都会导致硬件异常.
xdzy
2013-06-21
这家伙很懒,什么也没写!
这样处理就不出现硬件异常了,谢谢楼上各位提供的资源 ``` static rt_bool_t rtgui_filelist_view_on_folder_item(rtgui_object_t *object, struct rtgui_event *event) { rtgui_win_t *menu; rtgui_listbox_t *listbox; rtgui_filelist_view_t *view; listbox = RTGUI_LISTBOX(object); menu = RTGUI_WIN(rtgui_widget_get_toplevel(RTGUI_WIDGET(object))); view = RTGUI_FILELIST_VIEW(menu->user_data); /* hide window */ rtgui_win_hide(menu); switch (listbox->current_item) { case 0: { char *dir_ptr; dir_ptr = (char *) rtgui_malloc(256); rtgui_filelist_view_get_fullpath(view, dir_ptr, 256); rtgui_filelist_view_set_directory(view, dir_ptr); rtgui_free(dir_ptr); /* destroy menu window */ rtgui_win_destroy(menu); } break; case 1: /* destroy menu window */ rtgui_win_destroy(menu); break; default: /* destroy menu window */ rtgui_win_destroy(menu); break; } return RT_TRUE; } ```
amsl
2013-06-21
这家伙很懒,什么也没写!
rtgui中需要分发事件的控件都是container属性,即这些控件是从container派生的,处理这种问题的思路是: ``` /*处理控件自身事件的代码*/ //相关代码...... dispatch_event();//分发事件给子控件 return; ``` PAINT事件都需要处理,不能中途返回 MOUSE事件可以根据需要设置是否返回,一般不要返回,否则很容易使某个子控件漏掉该事件. 所以建议对于container及它的派生控件使用 ``` rtgui_container_dispatch_mouse_event(widget, event); ``` 是合适的 使用下面的方式不合适: ``` if(rtgui_container_dispatch_mouse_event(widget, event) == RT_TRUE) return; ``` 应用中需要根据自身的需求处理返回的问题。
fighter
2013-08-11
这家伙很懒,什么也没写!
当一个文件加下有几万张监控图片采用filelist_view 浏览图片会非常占用RAM空间图片越多占得RAM越大当监控器工作一定年限后系统就会在浏览图片是崩溃
撰写答案
登录
注册新账号
关注者
0
被浏览
4.8k
关于作者
softwind
这家伙很懒,什么也没写!
提问
41
回答
153
被采纳
0
关注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
【RT-Thread】【ci】【scons】将ci.attachconfig.yml和scons结合使用
2
Rt-thread中OTA下载后,bootloader不搬程序
3
ulog 日志 LOG_HEX 输出时间改为本地日期时间
4
在RT-Thread Studio中构建前执行python命令
5
研究一了一段时间RTT,直接标准版上手太难,想用nano,但又舍不得组件
热门标签
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
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
5
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部