解码LVGL事件

news/2025/11/3 21:22:43/文章来源:https://www.cnblogs.com/YouEmbedded/p/19188344

LVGL 事件系统

事件是 LVGL 响应用户操作(如点击、滑动)或控件状态变化的核心机制,通过 “事件绑定 - 回调函数” 实现交互逻辑。

事件核心特点

  • 多绑定支持:一个回调函数可绑定多个对象(如一个 “计数回调” 绑定两个按钮);一个对象可绑定多个回调函数(如按钮同时绑定 “单击回调” 和 “长按回调”),回调按绑定顺序执行。
  • 事件冒泡:给对象添加lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE)后,子对象的事件会传递给父对象;若父对象也启用冒泡,事件会继续向上传递(直到顶层屏幕),适用于批量处理子对象事件。
  • 状态化触发:回调函数可通过lv_event_get_code(e)区分事件类型(如单击、长按),仅处理目标事件。
  • 用户数据传递:绑定事件时可携带自定义数据(如标签指针),避免使用全局变量,提升代码模块化。

事件类型分类

事件分为 5 大类,核心事件及触发场景如下(完整定义见lvgl/src/core/lv_event.h):

事件类别 核心事件宏 触发场景(文件原文 + 补充说明)
输入设备事件 LV_EVENT_PRESSED 对象被首次按下(仅触发一次,区别于LV_EVENT_PRESSING的持续触发)
LV_EVENT_PRESSING 对象被持续按下(按下期间不断触发,适用于实时响应的场景,如拖动)
LV_EVENT_SHORT_CLICKED 对象被短按(按下后快速释放,未超过 “长按时间阈值”)
LV_EVENT_LONG_PRESSED 对象被长按(按下时间超过lv_conf.hLV_LONG_PRESS_TIME(默认 1000ms),仅触发一次)
LV_EVENT_LONG_PRESSED_REPEAT 长按后重复触发(长按时间超过阈值后,每隔LV_LONG_PRESS_REPEAT_TIME(默认 100ms)触发一次)
LV_EVENT_CLICKED 对象被单击(按下后释放,且未发生滑动,是最常用的交互事件)
LV_EVENT_RELEASED 对象被释放(无论是否滑动,只要按下后松开就触发,用于清理按下状态)
LV_EVENT_SCROLL 对象发生滑动(如列表滚动、滑动条拖动,滚动过程中持续触发)
LV_EVENT_FOCUSED 对象获得焦点(如输入框被点击、键盘 Tab 键切换到该对象)
LV_EVENT_DEFOCUSED 对象失去焦点(如点击其他区域、切换到其他控件)
绘图事件 LV_EVENT_COVER_CHECK 检查对象是否完全覆盖某个区域(用于优化绘图性能,避免无效刷新)
LV_EVENT_DRAW_MAIN_BEGIN 控件开始绘制主体区域(用于自定义绘图,如在按钮上额外绘制图标)
子对象管理事件 LV_EVENT_CHILD_CREATED 父对象新增子对象时触发(如给按钮添加标签时,按钮会收到该事件)
LV_EVENT_CHILD_DELETED 父对象的子对象被删除时触发(如删除按钮上的标签时,按钮会收到该事件)
自定义事件 LV_EVENT_LAST+0,LV_EVENT_LAST+1 用户自定义事件(如 “数据加载完成”“网络断开”,需手动调用lv_event_send()触发)

常用函数解析:

//头文件lv_obj_event.h
/*** 为对象添加事件回调函数(事件响应的核心入口,必用函数)* @param obj       目标对象指针(lv_obj_t*,不可为NULL),需绑定事件回调的对象(如按钮、滑块、标签等)* @param event_cb  事件回调函数(lv_event_cb_t),函数原型为void (*lv_event_cb_t)(lv_event_t* e),事件触发时自动执行;回调内可通过lv_event_xxx系列函数获取事件信息* @param filter    事件筛选器(lv_event_code_t),指定仅响应的事件类型;例:LV_EVENT_CLICKED(点击)、LV_EVENT_VALUE_CHANGED(值变化)、LV_EVENT_PRESSED(按下),填LV_EVENT_ALL可响应所有事件* @param user_data 自定义数据(void*),将随事件传递给回调函数;可通过lv_event_get_user_data(e)在回调中获取;常用于传递对象关联的上下文(如参数配置、关联控件指针)* @return          事件描述符指针(lv_event_dsc_t*),用于后续移除该回调(如lv_obj_remove_event_dsc);内存不足时返回NULL,需检查返回值避免空指针操作* @note            同一对象可添加多个回调,触发时按添加顺序执行;若需移除特定回调,需保存此返回的event_dsc;*                  user_data若为栈内存(如局部变量),需确保对象未销毁前内存不释放(建议用全局变量、静态变量或堆内存(lv_malloc分配));*                  回调函数中避免长时间阻塞操作(如死循环、延时),会导致界面卡顿甚至无响应*/
lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data);/*** 向对象手动发送指定事件(主动触发事件,常用调试或联动场景)* @param obj       目标对象指针(lv_obj_t*,不可为NULL),需接收事件的对象* @param event_code    事件类型(lv_event_code_t),需传入LVGL预定义事件值;例:手动触发按钮点击事件LV_EVENT_CLICKED、触发控件值更新LV_EVENT_VALUE_CHANGED* @param param     自定义参数(void*),将传递给对象的事件回调;无需传参时填NULL* @return          执行结果(lv_result_t):LV_RESULT_OK表示对象未被事件删除,LV_RESULT_INVALID表示对象在回调中被删除(后续不可操作该obj)* @note            手动发送事件会完整触发对象所有匹配该事件的回调,与用户操作触发的事件逻辑一致;*                  若回调中调用lv_obj_del(obj)删除当前对象,此函数返回LV_RESULT_INVALID,需立即停止对该obj的后续访问(如修改样式、获取属性);*                  不建议频繁发送LV_EVENT_DRAW系列渲染相关事件,会增加GPU/CPU负载,影响界面帧率*/
lv_result_t lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param);/*** 获取事件的原始触发对象(区分事件源头,常用冒泡场景)* @param e         事件描述符指针(lv_event_t*,不可为NULL),仅能从事件回调函数的参数中传入* @return          原始目标对象指针(lv_obj_t*),即最初触发事件的对象;例:点击子按钮时,即使事件冒泡到父容器,此函数仍返回子按钮* @note            与lv_event_get_current_target_obj()的核心区别:前者始终指向“事件源头”,后者指向“当前执行回调的对象”(如父容器回调中返回父容器);*                  常用于父容器回调中区分“哪个子控件触发了事件”(如多个按钮共用父容器回调时,通过此函数判断点击的按钮);*                  仅在事件回调内部调用有效,外部调用返回NULL*/
lv_obj_t * lv_event_get_target_obj(lv_event_t * e);/*** 移除对象中指定的事件回调(释放资源,避免内存泄漏)* @param obj       目标对象指针(lv_obj_t*,不可为NULL),需移除回调的对象* @param dsc       事件描述符指针(lv_event_dsc_t*,不可为NULL),即lv_obj_add_event_cb的返回值* @return          移除结果(bool):true表示移除成功,false表示描述符无效(如已移除、不属于该对象)* @note            移除后,该event_dsc指针失效,不可再使用;*                  若对象被删除(lv_obj_del(obj)),LVGL会自动清理其所有事件回调,无需手动调用此函数;*                  建议在对象关联的上下文销毁时(如页面关闭),手动移除回调,避免悬空指针风险*/
bool lv_obj_remove_event_dsc(lv_obj_t * obj, lv_event_dsc_t * dsc);/*** 获取触发事件的输入设备(判断输入类型,常用交互逻辑)* @param e         事件描述符指针(lv_event_t*,不可为NULL),仅能从事件回调函数参数传入* @return          输入设备指针(lv_indev_t*),例:触摸设备(LV_INDEV_TYPE_POINTER)、键盘(LV_INDEV_TYPE_KEYPAD)、旋转编码器(LV_INDEV_TYPE_ENCODER);非输入事件(如LV_EVENT_SIZE_CHANGED)返回NULL* @note            需配合lv_indev_get_type(indev)判断设备类型,例:区分事件是触摸触发还是键盘触发,从而执行不同逻辑;*                  仅在输入相关事件中有效(如LV_EVENT_CLICKED、LV_EVENT_KEY、LV_EVENT_ROTARY),其他事件返回NULL*/
lv_indev_t * lv_event_get_indev(lv_event_t * e);/*** 按回调函数地址移除事件(批量清理相同回调,常用统一管理场景)* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param event_cb  需移除的回调函数地址(lv_event_cb_t,不可为NULL),所有绑定该函数的回调都会被移除* @return          移除结果(bool):true表示至少移除1个回调,false表示未找到匹配的回调* @note            此函数会移除对象中所有绑定该event_cb的回调(无论filter和user_data是否相同);*                  若仅需移除某个特定回调(而非所有相同函数的回调),建议用lv_obj_remove_event_dsc(需保存event_dsc);*                  移除后,对应的event_dsc失效,不可再使用*/
bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb);
//头文件lv_event.h
/*** 向事件列表添加事件回调(事件系统核心注册接口)* @param list      事件列表指针(lv_event_list_t*,不可为NULL),需绑定回调的事件列表(通常从对象中获取,如obj->event_list)* @param cb        事件回调函数(lv_event_cb_t),函数原型为void (*lv_event_cb_t)(lv_event_t* e),事件触发时执行* @param filter    事件筛选器(lv_event_code_t),指定仅响应的事件类型;填LV_EVENT_ALL响应所有事件,填具体事件(如LV_EVENT_CLICKED)仅响应该事件* @param user_data 自定义数据(void*),将随事件传递给回调;可通过lv_event_get_user_data(e)在回调中获取;用于传递上下文信息(如关联控件、配置参数)* @return          事件描述符指针(lv_event_dsc_t*),用于后续移除该回调;内存不足时返回NULL,需检查返回值避免空指针操作* @note            同一事件列表可添加多个回调,触发时按添加顺序执行;若需精准移除单个回调,需保存此返回的event_dsc;*                  user_data若为栈内存(如局部变量),需确保事件列表生命周期内内存不释放(建议用全局变量、静态变量或lv_malloc分配的堆内存);*                  回调函数中避免执行耗时操作(如文件读写、延时),会阻塞事件处理流程,导致界面卡顿*/
lv_event_dsc_t * lv_event_add(lv_event_list_t * list, lv_event_cb_t cb, lv_event_code_t filter, void * user_data);/*** 向事件列表发送指定事件(主动触发事件,常用调试或联动场景)* @param list      事件列表指针(lv_event_list_t*,不可为NULL),需接收事件的目标事件列表* @param e         事件描述符指针(lv_event_t*,不可为NULL),需提前初始化(包含事件类型、目标对象、参数等信息)* @param preprocess 是否预处理(bool):true表示先执行标记LV_EVENT_PREPROCESS的回调,false按正常顺序执行* @return          执行结果(lv_result_t):LV_RESULT_OK表示事件处理完成,LV_RESULT_INVALID表示事件处理被中断(如调用lv_event_stop_processing)* @note            发送事件前需确保e的关键字段(如event_code、target、current_target)已正确初始化;*                  若回调中调用lv_event_stop_processing(e),此函数会提前返回,未执行的回调将被跳过;*                  不建议频繁发送LV_EVENT_DRAW系列渲染事件,会增加CPU/GPU负载,影响界面帧率*/
lv_result_t lv_event_send(lv_event_list_t * list, lv_event_t * e, bool preprocess);/*** 获取事件的原始目标(区分事件源头,常用冒泡场景)* @param e         事件描述符指针(lv_event_t*,不可为NULL),仅能从事件回调函数参数中传入* @return          原始目标指针(void*),即最初触发事件的对象/数据;例:子控件触发事件后冒泡到父容器,此函数仍返回子控件地址* @note            与lv_event_get_current_target(e)的核心区别:前者始终指向“事件源头”,后者指向“当前处理回调的目标”(如父容器回调中返回父容器);*                  需强制转换为对应类型使用(如lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e));*                  仅在事件回调内部调用有效,外部调用返回NULL*/
void * lv_event_get_target(lv_event_t * e);/*** 获取事件的当前目标(定位当前处理对象,常用多层级回调场景)* @param e         事件描述符指针(lv_event_t*,不可为NULL),仅能从事件回调函数参数中传入* @return          当前目标指针(void*),即当前正在执行回调的对象/数据;例:父容器处理子控件冒泡事件时,返回父容器地址* @note            常用于回调中判断“当前处理的对象是否为预期目标”(如避免父容器误处理非关联子控件的事件);*                  需强制转换为对应类型使用(如lv_obj_t* curr_obj = (lv_obj_t*)lv_event_get_current_target(e));*                  若事件未冒泡,当前目标与原始目标一致*/
void * lv_event_get_current_target(lv_event_t * e);/*** 获取事件类型(判断事件种类,回调核心逻辑分支依据)* @param e         事件描述符指针(lv_event_t*,不可为NULL),仅能从事件回调函数参数中传入* @return          事件类型(lv_event_code_t),即触发回调的事件种类,如LV_EVENT_CLICKED(点击)、LV_EVENT_VALUE_CHANGED(值变化)、LV_EVENT_DELETE(删除)* @note            是回调函数中分支逻辑的核心依据(例:if(lv_event_get_code(e) == LV_EVENT_CLICKED) { ... });*                  若为自定义事件,返回值为通过lv_event_register_id()注册的自定义ID;*                  不可直接将返回值与自定义整数比较,需用注册时保存的自定义事件ID*/
lv_event_code_t lv_event_get_code(lv_event_t * e);/*** 获取事件的自定义数据(回调中获取上下文,常用参数传递)* @param e         事件描述符指针(lv_event_t*,不可为NULL),仅能从事件回调函数参数中传入* @return          自定义数据指针(void*),即调用lv_event_add()时传入的user_data;未传数据时返回NULL* @note            是回调函数获取外部上下文的唯一方式(例:通过此函数获取关联的配置结构体、子控件指针);*                  需强制转换为对应类型使用(如my_config_t* cfg = (my_config_t*)lv_event_get_user_data(e));*                  若user_data指向堆内存,需确保回调中不提前释放,避免悬空指针*/
void * lv_event_get_user_data(lv_event_t * e);/*** 停止事件冒泡(阻止事件向上传递,常用边界控制)* @param e         事件描述符指针(lv_event_t*,不可为NULL),仅能从事件回调函数参数中传入* @note            仅对支持冒泡的事件有效(如LV_EVENT_CLICKED、LV_EVENT_VALUE_CHANGED);调用后,事件不再传递给父对象的事件列表;*                  需在回调早期调用(如回调函数开头),若已执行部分逻辑后调用,仅影响后续冒泡,不回滚已执行操作;*                  与lv_event_stop_processing(e)的区别:前者阻止事件向上冒泡,后者停止当前事件列表的后续回调执行*/
void lv_event_stop_bubbling(lv_event_t * e);

事件处理完整流程

事件处理的核心是:用户操作 / 系统触发 → 事件生成 → 传递到对象 → 执行绑定的回调函数。具体分 5 步,结合代码示例说明:

步骤 1:创建 UI 对象(事件的载体)

事件必须依附于具体的 UI 对象(如按钮、滑块等),先创建一个对象作为事件的 “接收者”。

// 创建一个按钮(作为事件载体)
lv_obj_t * btn = lv_btn_create(lv_scr_act()); // 在当前屏幕创建按钮
lv_obj_set_pos(btn, 100, 100); // 位置:x=100, y=100
lv_obj_set_size(btn, 120, 50); // 大小:宽120,高50

步骤 2:编写事件回调函数(事件的处理逻辑)

回调函数是事件触发后执行的代码,通过 LVGL 提供的lv_event_get_xxx函数获取事件详情(如事件类型、触发对象等)。

// 回调函数:处理按钮的点击、释放等事件
static void btn_event_cb(lv_event_t * e) {// 获取事件类型(判断是“点击”“释放”还是其他事件)lv_event_code_t code = lv_event_get_code(e);// 获取触发事件的原始对象(这里是按钮)lv_obj_t * btn = lv_event_get_target(e);// 根据事件类型执行不同操作if(code == LV_EVENT_CLICKED) {lv_obj_set_style_bg_color(btn, lv_color_hex(0xFF0000), LV_PART_MAIN); // 点击后变红}else if(code == LV_EVENT_RELEASED) {lv_obj_set_style_bg_color(btn, lv_color_hex(0x00FF00), LV_PART_MAIN); // 释放后变绿}
}

步骤 3:绑定回调函数到对象(建立事件与处理逻辑的关联)

通过lv_obj_add_event_cb函数,将回调函数绑定到对象上,并指定需要响应的事件类型(如 “点击”“释放”)。

// 给按钮绑定回调函数,指定响应“点击”和“释放”事件
lv_obj_add_event_cb(btn,               // 目标对象(按钮)btn_event_cb,      // 回调函数(上面定义的btn_event_cb)LV_EVENT_CLICKED | LV_EVENT_RELEASED,  // 响应的事件类型(点击+释放)NULL               // 自定义用户数据(这里无需传递,填NULL)
);
  • 绑定后,当按钮被点击或释放时,btn_event_cb会自动被调用。

步骤 4:事件的触发与传递(事件如何被触发并传递)

当用户操作对象(如点击按钮)或系统触发事件(如对象被删除)时,LVGL 会自动生成事件,并按规则传递:

  • 事件触发:例如用户用鼠标点击按钮,LVGL 的输入设备系统会检测到这个操作,生成LV_EVENT_CLICKED事件。

  • 事件传递(冒泡机制):事件会先传递给触发对象(按钮),执行其绑定的回调;若未被阻止,事件会向上 “冒泡” 到父对象(如按钮的父容器),执行父对象的回调。

    // 示例:给按钮的父容器也绑定回调,演示冒泡
    lv_obj_t * parent = lv_obj_create(lv_scr_act()); // 创建父容器
    lv_obj_set_size(parent, 300, 200);
    btn = lv_btn_create(parent); // 按钮的父对象是parent(此时按钮在容器内)// 父容器的回调(接收子按钮的冒泡事件)
    static void parent_event_cb(lv_event_t * e) {if(lv_event_get_code(e) == LV_EVENT_CLICKED) {LV_LOG_USER("父容器收到了按钮的点击事件(冒泡)");}
    }
    lv_obj_add_event_cb(parent, parent_event_cb, LV_EVENT_CLICKED, NULL);
    
    • 点击按钮时,会先执行btn_event_cb,再执行parent_event_cb(冒泡效果)。

步骤 5:回调中控制事件(可选:阻止冒泡或终止处理)

在回调函数中,可通过lv_event_stop_bubbling阻止事件继续向上传递,或用lv_event_stop_processing终止当前事件的所有后续处理。

static void btn_event_cb(lv_event_t * e) {if(lv_event_get_code(e) == LV_EVENT_CLICKED) {// 阻止事件冒泡到父容器lv_event_stop_bubbling(e); // 此时父容器的回调不会被执行}
}

总结:一句话流程

创建对象 → 写回调(处理逻辑) → 绑定回调到对象(指定事件) → 用户操作触发事件 → 事件传递(可冒泡) → 回调执行(可控制传递)。

自定义事件示例:

// 自定义事件ID(全局变量,运行时注册)
uint32_t MY_EVENT_CUSTOM;// 事件回调函数(用if-else判断事件类型,避免switch-case限制)
static void btn_event_cb(lv_event_t *e) {// 获取事件类型和目标按钮uint32_t event_code = lv_event_get_code(e);lv_obj_t *btn = lv_event_get_target(e);// 处理不同事件if (event_code == LV_EVENT_CLICKED) {// 点击按钮时触发:按钮变红色lv_obj_set_style_bg_color(btn, lv_color_hex(0xFF0000), LV_PART_MAIN);LV_LOG_USER("The button was clicked (system event)");} else if (event_code == MY_EVENT_CUSTOM) {// 自定义事件触发:按钮变绿色lv_obj_set_style_bg_color(btn, lv_color_hex(0x00FF00), LV_PART_MAIN);LV_LOG_USER("Received a custom event! parameters:%s", (char*)lv_event_get_param(e));}
}
// 创建对象→注册事件→发送事件
void test(void) 
{// 创建一个按钮作为事件目标lv_obj_t *btn = lv_btn_create(lv_scr_act());lv_obj_set_size(btn, 200, 100);  // 大小200x100lv_obj_center(btn);              // 屏幕居中lv_obj_set_style_bg_color(btn, lv_color_hex(0x0000FF), LV_PART_MAIN); // 初始蓝色// 注册事件回调(同时监听系统点击事件和自定义事件)lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);        // 系统事件lv_obj_add_event_cb(btn, btn_event_cb, MY_EVENT_CUSTOM, NULL);         // 自定义事件// 主动发送自定义事件(带参数"测试数据")lv_obj_send_event(btn, MY_EVENT_CUSTOM, "hello custom event");
}

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

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

相关文章

11.3号学习内容

阅读模型压缩的论文| https://doi.org/10.48550/arXiv.2010.03954 | header | | ----------------------------------------- | ------ | | | |

P11771 题解

blog。虽然糖丸了,但是卡了还是半天卡过去了。感谢出题人开 2s /kt!!最显然的暴力是,考虑直接算每个 \(i,j,k\) 的贡献。\(p_{i}\le p_k\wedge p_j\le p_k\):贡献为 \(0\)。 \(p_{i}>p_k\wedge p_j\le p_k\):…

MySQL排序算法

一、概述 ORDER BY的核心功能,是按照指定的单个或多个字段,对SELECT查询返回的结果集进行升序(ASC,默认)或降序(DESC)排列,以满足业务对数据有序性的需求。但要判断ORDER BY的实际执行效率,最直接的工具是EXP…

CSP-S 2025 饭堂寄

省流:\(100+48+0+0=148\),爆炸。 Day -2 考试前几天竟然发现有些感冒了。 Day -1 考试前一天晚上睡得比较晚,因为回到家都接近 11 点钟了。 Day 1 早上起来已经 9:30 了,起来开始打板子,其实这个时候已经感觉状态…

如何在github上使用github免费域名下预览自己的项目

一、新建自己的工程然后上传自己的工程文件,有首页的话记下首页的路径。 二、点击Settings 点击Pages,填写自己要访问的index.html文件路径

在ROS中安装PX4依赖实现Gazebo仿真

在ROS中安装PX4依赖实现Gazebo仿真最近这几天在做一个无人机项目,在配置gazebo仿真时出现了找不到px4的问题,但是又无法直接安装,需要自行编译 简单做一下记录 sudo apt install ninja-build exiftool ninja-build …

20232314 2024-2025-1 《网络与系统攻防技术》实验四实验报告

一、实验内容 1、恶意代码文件类型标识、脱壳与字符串提取 对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者,具体操作如下: (1)使用文件格式和类型识别工具,给出ra…

二、驱动基础(基于北京迅为电子)

一、基础Linux驱动的分类:字符设备(顺序访问)、块设备(随机访问)、网络设备(数据包收发) Linux内核源码的目录架构:arch(架构相关)、block(块设备)、crypto(加密算法)、Documentation(官方文档)、driv…

Linux驱动开发学习日记(一)

Linux驱动开发学习日记(一)整完无人机项目之后进行更新,具体怎么写还没想好,现在学的也比较迷糊

Windows 路由表详解

Windows 路由表详解windows 路由表详解 查看ip信息 字段说明IPv4 Address: ipv4地址,用于标识网络中的主机Subnet Mask: 子网掩码,分为 连续的1 和 连续的0 两部分, 可以简写为 /n, 例如 /24,表示高24位为1,剩下为…

微软 Foundry Local - 本地 AI 推理解决方案

微软在其 2025 Build 大会上发布了 Foundry Local,能够在本地设备上执行 AI 推理,意味着可以利用本地的 AI 算力,如:CPU/GPU/NPU;也让用户在隐私方面得到了充足的保障,还能有改善成本效益!Foundry Local 默认除…

如何启用cycloneDDS的iceoryx

共享内存交换 — Eclipse Cyclone DDS,0.11.0 首先我们需要先下载安装iceoryx,因为cycloneDDS如果要使用共享内存传输是依赖于这个插件的。顺带一提,只有同一节点的不同进程间会使用到共享内存,cycloneDDS是根据如…

老化车

老化车非常好 👍,这个问题在电子制造和测试领域里很关键。 “老化车”(又叫 Burn-in Cart 或 Aging Rack)是用于电子产品在出厂前做 老化测试(Burn-in Test) 的一种设备或平台。 下面我给你系统讲清楚 👇🧭…

Android Studio 2025.2.1 汉化中文包临时解决方案

打开 JetBrains 官网 Chinese ​(Simplified)​ Language Pack / 中文语言包 下载最新版 242.152 版本插件将 zh.242.152.jar 文件解压出来用压缩包工具打开 zh.242.152.jar 找到目录 META-INF 并打开用文本编辑工具打…

Markdown 学习训练

Markdown 学习训练 引用(使用>)这是我的第一篇博客,本篇博客是参照狂神说课程进行学习,目的是为了练习markdown使用语法。主要包含各级标题、字体、图片、代码块、超链接、表格使用语法练习。具体可前往typora官网…

jmeter设置中文页面的两种方法

JMeter设置中文界面有两种方法:临时设置(仅当前会话有效)和永久设置(修改配 置文件后永久生效)。 设置方法 1.临时设置(关闭后恢复英文): 打开JMeter,点击菜单栏“Options”→“Choose Language”→选择“Chi…

win10 下运行aoe2,报错,应用程序无法正常启动 0xc000022

控制面板 →搜索“启用或关闭 Windows 功能”找到并勾选 “旧版组件” → “DirectPlay” → 确定 → 重启电脑。

Python生成器表达式详解(含与列表推导式核心对比、别名探讨)

从“囤货”到“现做”:Python生成器表达式详解(含与列表推导式核心对比) 在Python中,处理数据时经常会遇到一个矛盾:既要简洁的语法,又要避免大量数据占用内存。列表推导式虽能简化代码,却会“一次性生成所有元…

在Fiddler中模拟网络中断,返回500错误的过程

开启断点在 Fiddler 菜单栏点击 Rules → Automatic Breakpoints,选择以下任一断点模式: Before Requests(请求发送前断点):可修改请求后再发送,适合模拟服务器因异常请求返回 500。 After Responses(响应返回后…

P4198 楼房重建 分析

题目概述 题目链接:https://www.luogu.com.cn/problem/P4198。 给出一个 \(x\) 轴长度为 \(n\),\(y\) 轴长度为 \(10^9\) 的二维平面。 一共有 \(n\) 天,第 \(i\) 天令坐标为 \(x_i\) 的线段变长为 \(y_i\)(屋顶就…