PUPANVR-LVGL UI主菜单及设置窗体框架(9)

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*/
}

总体的原则即,在新增加菜单及新增设置界面时,只需要修改对应的菜单数据配置即可!不需要改动其他的代码部分!这样来方便开发及维护!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/132962.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ArcGIS】NDVI估算植被覆盖度FVC

NDVI计算 植被覆盖度计算 Step1&#xff1a;调出栅格计算器工具 1、首先打开软件&#xff0c;然后在操作页面点击&#xff0c;自定义工具栏中——自定义模式。 2、再点击窗口中的命令选项。 3、在窗口右上角处搜索“栅格计算”。 4、然后&#xff0c;直接将栅格计算器直接…

docker 部署lnmp

目录 1、部署nginx\ 1.1、vim Dockerfile 1.2、 1.3、vim nginx.conf 2、部署mysql&#xff08;容器IP 为 172.18.0.20&#xff09; 2.1、vim Dockerfile 2.2、vim my.cnf 2.3、 3、部署php&#xff08;容器IP 为 172.18.0.30&#xff09; 3.1、 vim Dockerfile 3.2、…

CTF Misc(3)流量分析基础以及原理

前言 流量分析在ctf比赛中也是常见的题目&#xff0c;参赛者通常会收到一个网络数据包的数据集&#xff0c;这些数据包记录了网络通信的内容和细节。参赛者的任务是通过分析这些数据包&#xff0c;识别出有用的信息&#xff0c;例如登录凭据、加密算法、漏洞利用等等 工具安装…

ThreeJS-3D教学七-交互

在threejs中想要选中一个物体&#xff0c;点击或者鼠标悬浮&#xff0c;又或者移动端的touch事件&#xff0c;核心都是通过new THREE.Raycaster完成的。这里用到了一个概念&#xff0c;即我们点击时的 屏幕坐标 转换为 three中的3D坐标。 先看效果图&#xff1a; 代码是&#…

计算机毕业设计选什么题目好?springboot 大学餐厅菜品推荐和点评系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【机器学习】决策树原理及scikit-learn使用

文章目录 决策树详解ID3 算法C4.5算法CART 算法 scikit-learn使用分类树剪枝参数重要属性和接口 回归树重要参数&#xff0c;属性及接口交叉验证代码示例 一维回归的图像绘制 决策树详解 决策树&#xff08;Decision Tree&#xff09;是一种非参数的有监督学习方法&#xff0c;…

基于NLopt的C语言非线性优化案例

以官方给的例程&#xff0c;重新梳理&#xff0c;以供理解NLopt的使用。 问题被定义为&#xff1a; min ⁡ x ∈ R 2 x 2 s u b j e c t t o x 2 ≥ 0 , x 2 ≥ ( a 1 x 1 b 1 ) 3 , a n d x 2 ≥ ( a 2 x 1 b 2 ) 3 f o r p a r a m e t e r s a 1 2 , b 1 0 , a 2 − 1…

VulnHub 兰皮昂 1 Lampiao

一、信息收集 发现开发了22、80、1898端口 访问1898端口&#xff1a; 2.目录扫描 dirb http://192.168.103.179:1898 访问robots.txt目录 发现版本是 Drupal 7.54, 2017-02-01 二、漏洞利用 1.利用msf use 4 set RHOTS 192.168.103.179set RPORT 1898run #运行 shell #she…

Python in Visual Studio Code 2023年10月发布

排版&#xff1a;Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展于 2023 年 10 月发布&#xff01; 此版本包括以下公告&#xff1a; Python 调试器扩展更新弃用 Python 3.7 支持Pylint 扩展更换时的 Lint 选项Mypy 扩展报告的范围和守护程序模式G…

02Maven核心程序的下载与settings.xml文件的配置,环境变量的配置

Maven核心程序的解压与配置 Maven的下载与解压 Maven官网下载安装包 将下载的Maven核心程序压缩包apache-maven-3.8.4-bin.zip解压到一个非中文且没有空格的目录 Maven的核心配置文件 在Maven的解压目录conf中我们需要配置Maven的核心配置文件settings.xml 配置本地仓库位置…

【Node.js】路由

基础使用 写法一&#xff1a; // server.js const http require(http); const fs require(fs); const route require(./route) http.createServer(function (req, res) {const myURL new URL(req.url, http://127.0.0.1)route(res, myURL.pathname)res.end() }).listen…

Redis - php通过ssh方式连接到redis服务器

1.应用场景 主要用于使用php通过ssh方式连接到redis服务器&#xff0c;进行一些操作. 2.学习/操作 1.文档阅读 chatgpt & 其他资料 SSH - 学习与实践探究_ssh应用场景 2.整理输出 2.1 是什么 TBD 2.2 为什么需要「应用场景」 TBD 2.3 什么时候出现「历史发展」 TBD 2.4 …