温州网站开发流程,网站怎样投放广告位,装修公司名字大全参考,平台戚里带崇墉PUPA NVR UI主菜单及设置窗体框架
在设计UI时#xff0c;竟量把数据、控制、显示#xff0c;分开#xff0c;即MVC的一个模式吧#xff01;使用MVC这样的模式思想#xff0c;会让代码简洁不少#xff0c;逻辑也很清析#xff01; 具体的代码见#xff1a; PUPANVR这个…PUPA NVR UI主菜单及设置窗体框架
在设计UI时竟量把数据、控制、显示分开即MVC的一个模式吧使用MVC这样的模式思想会让代码简洁不少逻辑也很清析 具体的代码见 PUPANVR这个项目 https://gitee.com/jhting/pupanvr.git
UI主菜单
主菜单设计为NVR上比较传统的界面宫格方式如下图
定义菜单数据(M)
对于这样的菜单项目每一项目信息要求基本是一样的如有一个标题有一个图标对应的一个操作
所以可以定义一个针对项目定一个结构体
typedef struct{int menuItemID;char menuItemText[256];char menuItemImage[256];char menuItemFontAwesome[10];StViewConfigWinBaseFrameParamsItemInfo* itemConfigInfo;
}StMainMenuItemInfo;
然后针对产品所有主菜单定义一个列表
StMainMenuItemInfo gStMainMenuItemInfoList[] {{1, 基本设置, , \uf2c3, testiteminfo},{2, 通道管理, , \uf03d, NULL},{4, 录相回放, , \uf1c8, NULL},{4, 存储管理, , \uf1c0, NULL},{5, 报警设置, , \uf071, NULL},{6, 网络设置, , \uf26b, NULL},{7, 云平台, , \uf0ee, NULL},{8, 设备设置, , \uf085, NULL},
};这样后续如果新增、删除、或修改菜单项目只需要修改这个列表数据即可
在以上的数据结构中 StMainMenuItemInfo :
menuItemID: 定义菜单对应的ID值这样在单击时通过这个ID找到对应的数据;
menuItemText: 菜单显示的名称;
menuItemImage:菜单图片如果指定图标;
menuItemFontAwesome: 没有图标时使用fontAwesome的图标
itemConfigInfo 菜单里对应的菜单二级菜单项目这个对应数据会设置具体的菜单设置框加中这个定义见 TViewConfigWinBaseFrame 定义
定义菜单显示V
定义好上面的数据后再创建UI的绘制
对应的这个窗体类为TViewSysSetFrame
LVGL提供了方便的LAYOUT功能所以使用行、列的布局功能可以方便的自动排布好
在TViewSysSetFrame即初始化整个UI的控件创建及布局、数据加载
void TViewSysSetFrame::viewMenuItemInit()
{unsigned int i 0;int itemWidth 120;int itemHeight 120;int colNumber 4;//int rowNumber 2;int col 0;int row 0;static lv_coord_t col_dsc[] {itemWidth, itemWidth, itemWidth, itemWidth, LV_GRID_TEMPLATE_LAST};static lv_coord_t row_dsc[] {itemHeight, itemHeight, LV_GRID_TEMPLATE_LAST};StMainMenuItemInfo* pItem NULL;lv_obj_set_style_pad_all(m_viewHandle, 0, 0);lv_obj_t* lvObjMenuPanel lv_obj_create(m_viewHandle);int ctwidth lv_obj_get_content_width(m_viewHandle) - 20;int ctheight lv_obj_get_content_height(m_viewHandle) * 0.8;lv_obj_set_size(lvObjMenuPanel, ctwidth, ctheight);lv_obj_center(lvObjMenuPanel);lv_obj_set_style_border_width(lvObjMenuPanel, 0, 0);lv_obj_set_style_radius(lvObjMenuPanel, 0, 0);lv_obj_set_style_bg_color(lvObjMenuPanel, TViewStyle::DialogFrameBgColor, 0);lv_obj_set_layout(lvObjMenuPanel, LV_LAYOUT_GRID);lv_obj_set_style_grid_column_dsc_array(lvObjMenuPanel, col_dsc, 0);lv_obj_set_style_grid_row_dsc_array(lvObjMenuPanel, row_dsc, 0);lv_obj_set_grid_align(lvObjMenuPanel, LV_GRID_ALIGN_SPACE_AROUND, LV_GRID_ALIGN_SPACE_AROUND);for(i 0; i sizeof(gStMainMenuItemInfoList) / sizeof(gStMainMenuItemInfoList[0]); i){col i % colNumber;row i / colNumber;pItem gStMainMenuItemInfoList[i];//item lv_obj_t* lvObjItem lv_obj_create(lvObjMenuPanel);lv_obj_set_style_bg_color(lvObjItem, TViewStyle::DialogFrameBgColor, 0);lv_obj_set_scrollbar_mode(lvObjItem, LV_SCROLLBAR_MODE_OFF);lv_obj_set_style_border_width(lvObjItem, 0, 0);lv_obj_set_style_pad_all(lvObjItem, 0, 0);/*设置布局*/lv_obj_set_layout(lvObjItem, LV_LAYOUT_FLEX);lv_obj_set_flex_flow(lvObjItem, LV_FLEX_FLOW_COLUMN);/*让项目中的文本和图片分别都居中排列,这样设置后图片文本项都自动在水平垂直上都居中自动分配空间了*/lv_obj_set_flex_align(lvObjItem, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);lv_obj_set_user_data(lvObjItem, pItem);lv_obj_add_event_cb(lvObjItem, _menuitem_event_process, LV_EVENT_PRESSED, this);lv_obj_add_event_cb(lvObjItem, _menuitem_event_process, LV_EVENT_RELEASED, this);lv_obj_add_event_cb(lvObjItem, _menuitem_event_process, LV_EVENT_CLICKED, this);//imagelv_obj_t* plabItemImg lv_label_create(lvObjItem);lv_obj_set_style_text_color(plabItemImg, lv_color_hex(0xffffff), 0);lv_obj_set_style_text_font(plabItemImg, TViewFontUtils::getInstance()-getViewFont(VF_FONT_FontAwesome, 50), 0);lv_label_set_text(plabItemImg, pItem-menuItemFontAwesome);//textlv_obj_t* plabItemText lv_label_create(lvObjItem);lv_obj_set_style_text_color(plabItemText, lv_color_hex(0xffffff), 0); lv_obj_set_style_text_font(plabItemText, TViewFontUtils::getInstance()-getDefaultFont(16, 0), 0);lv_label_set_text(plabItemText, pItem-menuItemText);/*设置项目在行列位置*/lv_obj_set_grid_cell(lvObjItem, LV_GRID_ALIGN_STRETCH, col, 1,LV_GRID_ALIGN_STRETCH, row, 1);}//TViewFontUtils::getInstance()-releaseViewFont(VF_FONT_FontAwesome, 50, 0);
}以上代码根据定义好的 gStMainMenuItemInfoList 这个菜单数据列表自动的把每一项创建及排列好对 lvObjItem 具体项目分别绑定具体的事件
定义菜单操作逻辑©
事件控制如下
void TViewSysSetFrame::__menuitem_event_process(lv_event_t *event)
{lv_obj_t *obj event-target; if(event-code LV_EVENT_PRESSED){lv_obj_set_style_bg_color(obj, lv_palette_darken(LV_PALETTE_BLUE, 2), 0);}else if(event-code LV_EVENT_RELEASED){ lv_obj_set_style_bg_color(obj, TViewStyle::DialogFrameBgColor, 0);}else if(event-code LV_EVENT_CLICKED){ StMainMenuItemInfo* pItem (StMainMenuItemInfo*)obj-user_data;if(pItem){_menuitem_clicked_process(pItem-menuItemID); }}
}void TViewSysSetFrame::_menuitem_event_process(lv_event_t *event)
{TViewSysSetFrame* obj (TViewSysSetFrame*)event-user_data; obj-__menuitem_event_process(event);
}void TViewSysSetFrame::_menuitem_clicked_process(int id)
{TViewConfigWinBaseFrame* win NULL;StMainMenuItemInfo* itemInfo getMainMenuItemInfoByID(id);if(itemInfo){win new TViewConfigWinBaseFrame();win-setViewConfigWinTitle(itemInfo-menuItemText);win-setViewConfigWinBaseFrameParams(itemInfo-itemConfigInfo);win-viewShow();}}通过以上代码一个主菜单窗体即完成了代码量很少主要在设计UI时使用MVC这样的模式思想会让代码简洁不少逻辑也很清析
具体设置界面框架
在同一个产品中每一个设置界面的主体框架的风格应该是一致的所以就没有必要每一个设置界面都重复的窗体界面的代码
这里先造一个模子后面每一个设置界面套在这个模子里即可
具体设置窗体的风格如下 上方为一个标题栏中间显示窗体名称右边显示一个关闭按钮可以通过这个按钮退出
窗体的内容区左、右布局左边为一个二级菜单列表项右边为二级菜单的内容显示区。
有了上面的布局后代码也比较简单: TViewConfigWinBaseFrame 中先创建一个窗体先上、下布局的PANEL,再对上下的Panel分另左、右布局分别创建!
TViewConfigWinBaseFrame::TViewConfigWinBaseFrame()
{lv_obj_set_width(m_viewHandle, 800);lv_obj_set_height(m_viewHandle, 600);m_view_titleObj NULL;m_viewMenuItemList NULL;m_lastListItemBtnObj NULL;m_lvObjBodyRightPanel NULL;m_title ;m_lastListItemBtnObj NULL;m_stViewConfigWinBaseFrameParams NULL;lv_obj_center(m_viewHandle);lv_obj_refr_size(m_viewHandle);lv_obj_set_scrollbar_mode(m_viewHandle, LV_SCROLLBAR_MODE_OFF);lv_obj_clear_flag(m_viewHandle, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_style_pad_all(m_viewHandle, 0, 0);TViewStyle::getInstance()-setDalogModelViewWindowStyle(this);lv_obj_set_layout(m_viewHandle, LV_LAYOUT_FLEX);lv_obj_set_flex_flow(m_viewHandle, LV_FLEX_FLOW_COLUMN_WRAP);lv_obj_set_flex_align(m_viewHandle, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);lv_obj_set_style_pad_gap(m_viewHandle, 0, 0);/*top panel*/lv_obj_t* lvObjTopPanel lv_obj_create(m_viewHandle);lv_obj_set_width(lvObjTopPanel, this-getViewWidth());lv_obj_set_style_bg_color(lvObjTopPanel, lv_palette_darken(LV_PALETTE_BLUE_GREY, 2), 0);lv_obj_set_height(lvObjTopPanel, TOPPANNEL_HEIGHT);lv_obj_set_width(lvObjTopPanel, lv_obj_get_width(m_viewHandle));lv_obj_set_style_border_width(lvObjTopPanel, 0, 0);lv_obj_set_style_pad_all(lvObjTopPanel, 0, 0);lv_obj_set_style_radius(lvObjTopPanel, 0, 0);m_view_titleObj lv_label_create(lvObjTopPanel);lv_obj_set_style_text_color(m_view_titleObj, lv_color_hex(0xffffff), 0); lv_obj_set_style_text_font(m_view_titleObj, TViewFontUtils::getInstance()-getDefaultFont(20, 0), 0);lv_label_set_text(m_view_titleObj, 基本框架);lv_obj_set_style_text_align(m_view_titleObj, LV_TEXT_ALIGN_CENTER, 0);lv_obj_center(m_view_titleObj);/*关闭按钮*/lv_obj_t* btnObj lv_btn_create(lvObjTopPanel);lv_obj_set_width(btnObj, TOPPANNEL_HEIGHT - 10);lv_obj_set_height(btnObj, TOPPANNEL_HEIGHT - 10);lv_obj_set_pos(btnObj, this-getViewWidth() - TOPPANNEL_HEIGHT 10, 5);lv_obj_set_style_bg_color(btnObj, lv_palette_darken(LV_PALETTE_BLUE_GREY, 2), 0);lv_obj_set_style_border_width(btnObj, 0, 0);lv_obj_set_style_pad_all(btnObj, 0, 0);lv_obj_set_style_radius(btnObj, 0, 0);lv_obj_add_event_cb(btnObj, _closeBtn_event_handler, LV_EVENT_CLICKED, this);lv_obj_t * labelbtn lv_label_create(btnObj);lv_obj_set_style_text_font(labelbtn, TViewFontUtils::getInstance()-getDefaultFont(20, 0), 0);lv_label_set_text(labelbtn, X );lv_obj_center(labelbtn);/*body*/lv_obj_t* lvObjBodyPanel lv_obj_create(m_viewHandle);lv_obj_set_width(lvObjBodyPanel, this-getViewWidth());lv_obj_set_flex_grow(lvObjBodyPanel, 1);lv_obj_set_style_bg_color(lvObjBodyPanel, TViewStyle::DialogFrameBgColor, 0);lv_obj_set_style_border_width(lvObjBodyPanel, 0, 0);lv_obj_set_style_pad_all(lvObjBodyPanel, 0, 0);lv_obj_set_style_radius(lvObjBodyPanel, 0, 0);view_bodyPanelInit(lvObjBodyPanel);
}TViewConfigWinBaseFrame::~TViewConfigWinBaseFrame()
{LOG(INFO) TViewConfigWinBaseFrame: m_title , close! endl;
}void TViewConfigWinBaseFrame::setViewConfigWinTitle(const char* titleText)
{m_title titleText;lv_label_set_text(m_view_titleObj, titleText);
}void TViewConfigWinBaseFrame::setViewConfigWinBaseFrameParams(StViewConfigWinBaseFrameParamsItemInfo params[])
{m_stViewConfigWinBaseFrameParams params;view_configLoad();
}void TViewConfigWinBaseFrame::view_configLoad()
{int i 0;lv_obj_t* btn NULL;if(!m_stViewConfigWinBaseFrameParams){return;}if(!m_viewMenuItemList){return;}StViewConfigWinBaseFrameParamsItemInfo* item m_stViewConfigWinBaseFrameParams[i];while(item){if(!item-itemText){break;}if(strlen(item-itemText) 0){break;}printf(add lv_list_add_btn:%s\n, item-itemText);btn lv_list_add_btn(m_viewMenuItemList, NULL, item-itemText);lv_obj_set_style_border_width(btn, 0, 0);lv_obj_set_style_pad_all(btn, 20, 0);lv_obj_set_style_text_font(btn, TViewFontUtils::getInstance()-getDefaultFont(16, 0), 0);lv_obj_set_style_bg_color(btn, lv_palette_darken(LV_PALETTE_BLUE_GREY, 3), 0);lv_obj_set_style_text_color(btn, lv_color_hex(0xFFFFFF), 0);/*set item to button userdata, when button click can get item config!*/lv_obj_set_user_data(btn, item);lv_obj_add_event_cb(btn, _menuItem_event_handler, LV_EVENT_CLICKED, this);item m_stViewConfigWinBaseFrameParams[i];}
}void TViewConfigWinBaseFrame::view_bodyPanelInit(lv_obj_t* bodyPanel)
{lv_obj_set_layout(bodyPanel, LV_LAYOUT_FLEX);lv_obj_set_flex_flow(bodyPanel, LV_FLEX_FLOW_ROW);lv_obj_set_flex_align(bodyPanel, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);lv_obj_set_style_pad_gap(bodyPanel, 0, 0);lv_obj_refr_size(m_viewHandle);lv_obj_refr_size(bodyPanel);//leftlv_obj_t* lvObjBodyLeftPanel lv_obj_create(bodyPanel); lv_obj_set_width(lvObjBodyLeftPanel, 150);lv_obj_set_height(lvObjBodyLeftPanel, lv_obj_get_height(m_viewHandle) - TOPPANNEL_HEIGHT - 5); lv_obj_set_style_border_width(lvObjBodyLeftPanel, 0, 0);lv_obj_set_style_pad_all(lvObjBodyLeftPanel, 0, 0);lv_obj_set_style_radius(lvObjBodyLeftPanel, 0, 0); lv_obj_set_style_bg_color(lvObjBodyLeftPanel, lv_palette_darken(LV_PALETTE_BLUE_GREY, 3), 0);//rightm_lvObjBodyRightPanel lv_obj_create(bodyPanel); lv_obj_set_flex_grow(m_lvObjBodyRightPanel, 1); lv_obj_set_height(m_lvObjBodyRightPanel, lv_obj_get_height(m_viewHandle) - TOPPANNEL_HEIGHT - 5); lv_obj_set_style_border_width(m_lvObjBodyRightPanel, 0, 0);lv_obj_set_style_pad_all(m_lvObjBodyRightPanel, 0, 0);lv_obj_set_style_radius(m_lvObjBodyRightPanel, 0, 0); lv_obj_set_style_bg_color(m_lvObjBodyRightPanel, TViewStyle::DialogFrameBgColor, 0);//left listm_viewMenuItemList lv_list_create(lvObjBodyLeftPanel);lv_obj_set_width(m_viewMenuItemList, 150);lv_obj_set_style_border_width(m_viewMenuItemList, 0, 0);lv_obj_set_style_pad_all(m_viewMenuItemList, 0, 0);lv_obj_set_style_radius(m_viewMenuItemList, 0, 0); //lv_obj_set_size(list2, lv_pct(40), lv_pct(100));//lv_obj_align(list, LV_ALIGN_TOP_RIGHT, 0, 0);lv_obj_set_style_bg_color(m_viewMenuItemList, lv_palette_darken(LV_PALETTE_BLUE_GREY, 3), 0);lv_obj_set_flex_flow(m_viewMenuItemList, LV_FLEX_FLOW_COLUMN);view_configLoad();
}void TViewConfigWinBaseFrame::_closeBtn_event_handler(lv_event_t* event)
{TViewConfigWinBaseFrame* obj (TViewConfigWinBaseFrame*)event-user_data; obj-viewHide();delete obj; /*delete instance of TViewConfigWinBaseFrame*/
}void TViewConfigWinBaseFrame::_menuItem_event_handler(lv_event_t* event)
{TViewConfigWinBaseFrame* obj (TViewConfigWinBaseFrame*)event-user_data;if(obj-m_lastListItemBtnObj){lv_obj_set_style_bg_color(obj-m_lastListItemBtnObj, lv_palette_darken(LV_PALETTE_BLUE_GREY, 3), 0);}obj-m_lastListItemBtnObj event-target;printf(_menuItem_event_handler click!\n);lv_obj_set_style_bg_color(obj-m_lastListItemBtnObj, TViewStyle::DialogFrameBgColor, 0);StViewConfigWinBaseFrameParamsItemInfo* item (StViewConfigWinBaseFrameParamsItemInfo*)lv_obj_get_user_data(obj-m_lastListItemBtnObj);if(!item){return;}if(item item-funGetFrame){item-funGetFrame(obj-m_lvObjBodyRightPanel);}}TViewConfigWinBaseFrame 这个UI类中对外提供了两个方法一个是设置当前窗体的标题及具体内容项目
void setViewConfigWinTitle(const char* titleText);
void setViewConfigWinBaseFrameParams(StViewConfigWinBaseFrameParamsItemInfo params[]);在回到 TViewSysSetFrame 这个类中的事件中主菜单中的一个项目单击时具体的窗体即是如下创建的:
void TViewSysSetFrame::_menuitem_clicked_process(int id)
{TViewConfigWinBaseFrame* win NULL;StMainMenuItemInfo* itemInfo getMainMenuItemInfoByID(id);if(itemInfo){win new TViewConfigWinBaseFrame();win-setViewConfigWinTitle(itemInfo-menuItemText);win-setViewConfigWinBaseFrameParams(itemInfo-itemConfigInfo);win-viewShow();}}对于设置窗体的关闭及窗体对像的Free是通过 TViewConfigWinBaseFrame 中的 _closeBtn_event_handler 事件触发的!
void TViewConfigWinBaseFrame::_closeBtn_event_handler(lv_event_t* event)
{TViewConfigWinBaseFrame* obj (TViewConfigWinBaseFrame*)event-user_data; obj-viewHide();delete obj; /*delete instance of TViewConfigWinBaseFrame*/
}总体的原则即在新增加菜单及新增设置界面时只需要修改对应的菜单数据配置即可不需要改动其他的代码部分这样来方便开发及维护!