[LVGL] 布局系统 lv_flex, lv_grid | 输入设备 lv_indev | union

第五章:布局系统(lv_flex, lv_grid)

欢迎回来!

在第四章:样式(lv_style)中,我们掌握了如何通过色彩、字体和圆角等特性美化部件。当界面元素具备视觉吸引力后,如何优雅地组织它们便成为新的挑战。

设想我们拥有多个精美按钮,希望实现以下布局效果:

  • 横向/纵向等距排列
  • 屏幕尺寸变化时自动适配
  • 动态增删元素时自动调整

传统手工计算坐标的方式显然低效且难以维护,这正是布局系统的价值所在。

布局系统核心价值

LVGL布局系统受现代网页设计(CSS Flexbox/Grid)启发,通过声明式配置实现:

在这里插入图片描述

布局类型概览

布局类型适用场景典型应用
弹性布局单向流式排列导航栏|设置项列表
网格布局二维矩阵排列仪表盘|相册缩略图

启用布局模块

lv_conf.h中激活配置:

/*==================* 布局模块*================*/
#define LV_USE_FLEX 1  // 启用弹性布局
#define LV_USE_GRID 1  // 启用网格布局

弹性布局(lv_flex)

1. 容器初始化

lv_obj_t * flex_container = lv_obj_create(screen_main);
lv_obj_set_size(flex_container, LV_PCT(90), LV_PCT(80)); // 相对父容器90%宽/80%高
lv_obj_set_layout(flex_container, LV_LAYOUT_FLEX);       // 声明弹性容器

2. 排列方向控制

// 横向排列(可换行)
lv_obj_set_flex_flow(flex_container, LV_FLEX_FLOW_ROW_WRAP);// 纵向排列(可换列)
lv_obj_set_flex_flow(flex_container, LV_FLEX_FLOW_COLUMN_WRAP);

3. 对齐方式

// 主轴居中|交叉轴居中|轨道居中
lv_obj_set_flex_align(flex_container, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);

4. 空间分配

lv_obj_t * expand_btn = lv_button_create(flex_container);
lv_obj_set_flex_grow(expand_btn, 2);  // 占据剩余空间2份lv_obj_t * normal_btn = lv_button_create(flex_container);
lv_obj_set_flex_grow(normal_btn, 1);  // 占据剩余空间1份

5. 间距控制

static lv_style_t flex_style;
lv_style_init(&flex_style);
lv_style_set_pad_column(&flex_style, 10);  // 列间距10像素
lv_style_set_pad_row(&flex_style, 15);     // 行间距15像素
lv_obj_add_style(flex_container, &flex_style, 0);

网格布局(lv_grid)

1. 容器初始化

lv_obj_t * grid_container = lv_obj_create(screen_main);
lv_obj_set_layout(grid_container, LV_LAYOUT_GRID);  // 声明网格容器

2. 网格结构定义

// 列定义:固定100px|弹性1份|弹性2份
static int32_t col_dsc[] = {100, LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST};// 行定义:自适应内容高度|弹性3份
static int32_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_FR(3), LV_GRID_TEMPLATE_LAST};lv_obj_set_grid_dsc_array(grid_container, col_dsc, row_dsc);

3. 单元格定位

// 按钮定位到(0,0)单元格,横向居左|纵向居顶
lv_obj_t * btn = lv_button_create(grid_container);
lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_START, 0, 1,   // 列:起始对齐,第0列,跨1列LV_GRID_ALIGN_START, 0, 1);  // 行:起始对齐,第0行,跨1行// 标签跨两列
lv_obj_t * label = lv_label_create(grid_container);
lv_obj_set_grid_cell(label,LV_GRID_ALIGN_CENTER, 1, 2,  // 列:居中,第1列,跨2列LV_GRID_ALIGN_CENTER, 0, 1); // 行:居中,第0行,跨1行

布局系统工作原理

处理流程

在这里插入图片描述

核心机制

  1. 注册机制通过lv_obj_set_layout()将容器注册到布局系统
  2. 延迟计算:在屏幕刷新周期统一处理布局计算
  3. 动态响应:容器尺寸变化或子元素增减时自动触发重新布局

实践

  1. 组合使用:在复杂界面中混合使用FlexGrid布局
  2. 响应式设计:结合LV_PCT百分比单位和媒体查询实现自适应
  3. 性能优化避免深层嵌套布局,控制刷新频率
  4. 样式分离:将布局样式与视觉样式分离管理

结论

通过本章学习,我们掌握了:

  • 弹性布局的流式排列空间分配技巧
  • 网格布局的二维矩阵定位方法
  • 布局系统的底层运作原理
  • 间距控制与对齐策略

布局系统的引入使界面开发从手工计算迈向声明式配置,极大提升了开发效率和可维护性。

下一章我们将探索用户交互的核心——输入设备管理

下一章:输入设备(lv_indev)


github: https://github.com/lvy010/Cpp-Lib-test/tree/main/LVGL/indev

第六章:输入设备(lv_indev)

在第五章:布局(lv_flex, lv_grid)中,我们已成为屏幕布局的大师,能够确保界面元素美观且自适应。但若用户无法真正触摸交互这些精心设计的界面,再惊艳的UI又有何用?

如何才能让那个完美居中、蓝色圆角按钮真正被点击?

这正是**输入设备(lv_indev)**大显身手之时~

假设我们的设备拥有物理触摸屏、鼠标、键盘甚至旋转编码器,LVGL需要通过某种方式理解用户通过这些物理输入设备的操作,并将这些动作转化为屏幕上控件(如按钮、滑块或文本输入框)能够理解和响应的指令

lv_indev模块就像用户交互的通用翻译器。

它接收来自硬件的原始信息(例如"手指触摸了X,Y坐标"或"Enter键被按下"),并将其转化为GUI可理解的语义事件。

这使得LVGL应用能够响应多样化的物理输入,而无需为每个交互编写复杂的硬件专用代码。

本章目标是理解如何连接常见输入设备——触摸屏(属于"指针"类设备),让LVGL按钮能够响应点击操作

什么是lv_indev

lv_indev(LVGL输入设备缩写,代码中以lv_indev_t结构体表示)是表征单个输入硬件设备的对象。

它充当微控制器原始输入数据与LVGL事件系统之间的桥梁。

lv_indev_t对象管理的关键要素:

  • 设备类型:属于触摸屏、键盘还是编码器?
  • 数据读取:需要开发者提供的特殊函数(“读取回调”)来获取硬件当前状态
  • 当前状态:按压/释放状态、指向位置或激活的按键
  • 关联显示:该输入设备控制的显示设备(回忆第二章:显示设备(lv_display))

输入设备类型(LV_INDEV_TYPE_

LVGL支持多种输入设备类别:

类型描述典型硬件
LV_INDEV_TYPE_POINTER能够指向屏幕具体坐标并触发按压/释放动作的设备触摸屏、鼠标、轨迹球
LV_INDEV_TYPE_KEYPAD提供按键输入的设备,常用于导航和文本输入物理键盘、数字键盘
LV_INDEV_TYPE_ENCODER带有增量旋转(左/右)和可选按压按钮的旋转设备旋钮编码器、滚轮
LV_INDEV_TYPE_BUTTON映射到屏幕坐标的物理按键(如设备外壳上的实体按钮) 前面板按键

本章将以LV_INDEV_TYPE_POINTER类型的触摸屏为例进行说明。

连接第一个输入设备(触摸屏)

让我们配置基础触摸屏功能,使LVGL能够检测按钮的触摸操作。

1. 创建输入设备对象

首先需要通过创建lv_indev_t对象告知LVGL存在输入设备。

该操作必须在显示设备(lv_display)创建之后执行。

#include "lvgl.h" // 始终包含主LVGL头文件// 在应用初始化函数中(如main.c或app_init())
void setup_input_device() 
{// 确保显示设备已初始化(例如调用第二章的setup_display())// lv_init();// setup_display(); // 需在输入设备设置前调用!// 1. 创建输入设备对象lv_indev_t * my_touchpad_indev = lv_indev_create();// ... 后续配置步骤在此添加
}
  • lv_indev_create():创建lv_indev_t对象,默认关联到首个创建的显示设备
  • lv_indev_t * my_touchpad_indev:该变量持有输入设备的操作句柄

2. 设置设备类型

告知LVGL输入设备类型,触摸屏属于LV_INDEV_TYPE_POINTER

// ...(接续前文代码)void setup_input_device() 
{lv_indev_t * my_touchpad_indev = lv_indev_create();// 2. 设置输入设备类型为POINTERlv_indev_set_type(my_touchpad_indev, LV_INDEV_TYPE_POINTER);// ... 后续配置步骤在此添加
}

3. 实现读取回调函数

这是最关键的部分!LVGL需要通过开发者提供的"读取回调"函数定期获取实际触摸数据。

my_touchpad_read函数需要完成:

  • 读取触摸的当前状态(按压或释放)
  • 若处于按压状态,读取X/Y坐标
  • 填充lv_indev_data_t结构体传递这些信息
// 将触摸数据存储为全局变量以便硬件驱动更新
//(例如在中断服务例程或主循环轮询中更新)
static int32_t touch_x = 0;
static int32_t touch_y = 0;
static bool touch_pressed = false; // 触摸屏激活时为true// *** 重要:需替换为实际硬件读取函数!***
// 以下仅为演示概念占位符
// 实际嵌入式系统中应读取触摸控制器IC数据
// 示例:*x = get_actual_touch_x(); *y = get_actual_touch_y(); *is_pressed = is_touch_down();void read_touchscreen_hardware(int32_t *x, int32_t *y, bool *is_pressed) 
{// 演示用模拟输入(如PC模拟器中的鼠标)// 实际应用中应从触摸传感器获取真实数据:*x = touch_x;*y = touch_y;*is_pressed = touch_pressed;
}// ****************************************************************************// 3. 自定义读取回调函数
void my_touchpad_read(lv_indev_t * indev, lv_indev_data_t * data) {// 从实际触摸硬件读取当前状态read_touchscreen_hardware(&touch_x, &touch_y, &touch_pressed);if (touch_pressed) {data->state = LV_INDEV_STATE_PRESSED; // 告知LVGL按压状态data->point.x = touch_x;              // 设置X坐标data->point.y = touch_y;              // 设置Y坐标} else {data->state = LV_INDEV_STATE_RELEASED; // 告知LVGL释放状态}
}
  • lv_indev_t * indev:触发回调的输入设备对象指针
  • lv_indev_data_t * data:必须填充当前输入数据的结构体
  • LV_INDEV_STATE_PRESSED / LV_INDEV_STATE_RELEASED:指针设备的两种基本状态
  • data->point.x, data->point.y:按压状态时的坐标位置

4. 连接读取回调

最后将my_touchpad_read函数关联至输入设备对象。

// ...(接续前文代码)void setup_input_device() 
{lv_indev_t * my_touchpad_indev = lv_indev_create();lv_indev_set_type(my_touchpad_indev, LV_INDEV_TYPE_POINTER);// 4. 关联读取回调函数lv_indev_set_read_cb(my_touchpad_indev, my_touchpad_read);
}

现在调用setup_input_device()后,LVGL将周期调用my_touchpad_read获取触摸状态,并据此判断控件(如第三章:控件(lv_obj)中的按钮)是否被点击

若结合第四章:样式(lv_style)中的LV_STATE_PRESSED样式,我们甚至能看到按钮在触摸时的颜色变化

理解控件组(适用于键盘/编码器)

POINTER设备通过直接点击屏幕坐标交互

KEYPADENCODER设备则通过"焦点"与控件交互。

想象用键盘导航网页:按Tab键在按钮间切换焦点,Enter键点击焦点按钮。

LVGL使用**控件组(lv_group_t)**实现此机制。

  • 创建组lv_group_t * g = lv_group_create();
  • 添加控件至组lv_group_add_obj(g, my_button);(对所有需导航的交互控件执行此操作)
  • 为输入设备分配组lv_indev_set_group(my_keypad_indev, g);

my_keypad_read回调报告LV_KEY_NEXT时,焦点将自动在g组的控件间切换

(Qt的话,有信号和槽机制)

[Qt] 信号和槽(1) | 本质 | 使用 | 自定义

[Qt] 信号和槽(2) | 多对多 | disconnect | 结合lambda | sum

输入设备工作原理

让我们观察触摸事件从硬件LVGL控件的传递过程。

  1. 轮询/读取:LVGL运行周期性定时器(由第一章:配置(lv_conf.h)中的LV_DEF_REFR_PERIOD控制,通常10-50ms)。该定时器触发lv_indev_read_timer_cb,进而调用各注册输入设备的lv_indev_read
  2. 读取回调lv_indev_read调用开发者实现的my_touchpad_read函数,从硬件读取原始X/Y坐标和触摸状态
  3. 数据处理:将原始数据填入lv_indev_data_t结构体并返回
  4. 查找目标对象:LVGL获取原始输入数据后,对指针设备会基于X/Y坐标遍历显示设备上的所有活动控件(从顶层系统层到底层),查找位于触摸点下的控件。此过程涉及坐标和可见性检查
  5. 状态与事件管理:确定目标控件后,LVGL更新其内部状态(如LV_STATE_PRESSED)并触发相关事件(如LV_EVENT_PRESSEDLV_EVENT_CLICKEDLV_EVENT_RELEASED)。若按压状态移动可能触发滚动或拖拽

简化序列图如下:

在这里插入图片描述

LVGL内部代码解析:

调用lv_indev_create()时,LVGL会为lv_indev_t结构体分配内存。

该结构体保存指向读取回调函数的指针、设备类型内部状态变量关联显示设备指针

核心逻辑位于src/indev/lv_indev.c,以下是简化代码片段:

// 摘自lv_indev.c(简化版)
lv_indev_t * lv_indev_create(void)
{// 为输入设备对象分配内存lv_indev_t * indev = lv_ll_ins_head(indev_ll_head);// ... 初始化默认值 ...// 创建周期性调用读取函数的定时器indev->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_DEF_REFR_PERIOD, indev);// ...return indev;
}void lv_indev_set_read_cb(lv_indev_t * indev, lv_indev_read_cb_t read_cb)
{// 存储开发者提供的读取回调函数指针indev->read_cb = read_cb;
}void lv_indev_read(lv_indev_t * indev)
{lv_indev_data_t data;// 调用开发者实现的读取回调if(indev->read_cb) {indev->read_cb(indev, &data);}// ... 根据indev->type处理data ...if(indev->type == LV_INDEV_TYPE_POINTER) {indev_pointer_proc(indev, &data); // 处理指针数据}// ... 其他类型处理(键盘、编码器、按钮)...
}static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) 
{// ... 从data->point更新内部'act_point' ...// ... 通过pointer_search_obj()查找指针下对象 ...// ... 更新内部状态(如i->pointer.act_obj, i->state)...if (i->state == LV_INDEV_STATE_PRESSED) {indev_proc_press(i); // 处理按压逻辑} else {indev_proc_release(i); // 处理释放逻辑}
}static void indev_proc_press(lv_indev_t * indev) 
{// ... 检测新对象、长按、滚动的逻辑 ...// 若启用,向活动对象(indev_obj_act)发送LV_EVENT_PRESSED事件// 示例:// lv_obj_send_event(indev_obj_act, LV_EVENT_PRESSED, indev_act);
}// lv_indev.h中完整的lv_indev_t定义
// 包含输入设备状态和配置的所有相关数据
typedef struct _lv_indev_t 
{// ... 其他成员 ...lv_indev_type_t type;            /**< 输入设备类型(POINTER, KEYPAD, ENCODER, BUTTON) */lv_indev_read_cb_t read_cb;      /**< 输入设备数据读取函数 */lv_indev_state_t state;          /**< 当前状态(PRESSED或RELEASED) */struct _lv_display_t * disp;     /**< 关联的显示设备 */lv_timer_t * read_timer;         /**< 周期性调用read_cb的定时器 */lv_group_t * group;              /**< 针对KEYPAD/ENCODER:交互的控件组 */// ... 指针、键盘等内部状态变量 ...// 例如:lv_point_t pointer.act_point; 当前坐标// 例如:uint32_t keypad.last_key; 最后按下的键// ... 更多手势、长按、滚动相关参数 ...
} lv_indev_t;

这种内部结构和处理流程确保了LVGL能够高效处理多种输入源,将底层硬件细节与GUI逻辑解耦。

代码功能

lv_indev_create()函数是LVGL输入设备系统的核心接口,用于创建并初始化一个输入设备实例。

函数返回lv_indev_t结构体指针,该结构体存储输入设备的全部运行时数据。

内存分配与初始化

lv_ll_ins_head(indev_ll_head)通过链表管理器为输入设备分配内存,同时将新设备插入全局链表头部

返回的lv_indev_t指针包含以下关键字段:

  • read_timer:通过lv_timer_create()创建定时器,周期性地调用lv_indev_read_timer_cb触发输入事件处理
  • type:初始化为LV_INDEV_TYPE_NONE,需通过lv_indev_set_type()显式设置
  • read_cb:初始化为NULL,需通过lv_indev_set_read_cb()绑定具体设备的读取函数
回调机制实现

lv_indev_set_read_cb()将开发者实现的设备读取函数指针存入indev->read_cb。当定时器触发lv_indev_read()时,会通过该指针调用具体设备的读取逻辑:

if(indev->read_cb) 
{indev->read_cb(indev, &data); // 回调开发者实现的硬件读取接口
}
输入数据处理流程
  1. 类型分发:根据indev->type进入对应处理器。以触摸屏(LV_INDEV_TYPE_POINTER)为例:

    indev_pointer_proc(indev, &data); // 处理坐标数据
    
  2. 状态机处理:在indev_pointer_proc()中:

    • 更新坐标act_point和当前活动对象act_obj
    • 根据state字段(PRESSED/RELEASED)分发给indev_proc_press()indev_proc_release()
  3. 事件生成:在按压处理中通过lv_obj_send_event()发送标准事件:

    lv_obj_send_event(indev_obj_act, LV_EVENT_PRESSED, indev_act);
    
关键数据结构

lv_indev_t包含输入设备的完整上下文:

typedef struct _lv_indev_t 
{lv_indev_type_t type;        // 设备类型标识lv_indev_read_cb_t read_cb;  // 设备级读取回调lv_indev_state_t state;      // PRESSED/RELEASED状态struct _lv_display_t * disp; // 绑定到特定显示器lv_timer_t * read_timer;     // 输入轮询定时器union {lv_point_t act_point;   // 指针设备当前坐标uint32_t last_key;      // 键盘设备最后按键};// ...其他手势/滚动参数...
} lv_indev_t;
⭕union

union 是一种特殊的 C 语言结构,允许同一块内存存储不同的数据类型(如 lv_point_tuint32_t),但同一时间只能使用其中一个成员,以节省内存空间

20.(C语言)联合和枚举全

code:

union {lv_point_t act_point;  // 用于存储指针坐标(如触摸屏位置)uint32_t last_key;     // 用于存储键盘按键值
};
  • 共享内存act_pointlast_key 共用同一块内存,修改其中一个会影响另一个的值
  • 应用场景:适合在设备只能触发一种输入(如触摸或按键)时复用内存,减少资源占用。

调用

开发者需要实现三个基础操作:

  1. 创建设备实例
  2. 设置设备类型
  3. 绑定读取回调
lv_indev_t * touchpad = lv_indev_create();
lv_indev_set_type(touchpad, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(touchpad, my_touchpad_read);

总结

至此我们已成功为LVGL应用连接输入设备!本章要点包括:

  • lv_indev是处理用户输入的核心模块
  • LVGL支持多种输入设备类型
  • 如何创建lv_indev_t对象、设置类型并提供硬件数据读取回调
  • lv_indev如何将原始输入转化为控件交互
  • "控件组"对键盘和编码器导航的重要性

配置完输入设备后,我们精心设计的样式化控件已具备完整交互能力!下一步将深入探索控件如何响应这些交互事件。

下一章:事件系统(lv_event)

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

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

相关文章

Linux中的mkdir命令

基本语法mkdir 命令的基本语法如下&#xff1a;mkdir [选项] 目录名创建单个目录要创建一个新目录&#xff0c;只需在 mkdir 后跟上目录名称。例如&#xff1a;mkdir new_folder这会在当前工作目录下创建一个名为 new_folder 的目录。创建多个目录可以一次性创建多个目录&#…

基于大数据的美食视频播放数据可视化系统 Python+Django+Vue.js

本文项目编号 25003 &#xff0c;文末自助获取源码 \color{red}{25003&#xff0c;文末自助获取源码} 25003&#xff0c;文末自助获取源码 目录 一、系统介绍二、系统录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状 六、核心代码6.1 查询数据6.2 新…

微信小程序精品项目-基于springboot+Android的计算机精品课程学习系统(源码+LW+部署文档+全bao+远程调试+代码讲解等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

(五)系统可靠性设计

2024年博主考软考高级系统架构师没通过&#xff0c;于是决定集中精力认真学习系统架构的每一个环节&#xff0c;并在2025年软考中取得了不错的成绩&#xff0c;虽然做信息安全的考架构师很难&#xff0c;但找对方法&#xff0c;问题就不大&#xff01; 本文主要是博主在学习过程…

Shuffle SOAR使用学习经验

Shuffle SOAR 1. 基础操作与配置1.1 环境搭建与系统要求1.1.1 硬件与操作系统要求Shuffle SOAR 平台作为一款开源的安全编排、自动化与响应&#xff08;SOAR&#xff09;工具&#xff0c;其部署方式灵活&#xff0c;支持云端和自托管两种模式。对于自托管部署&#xff0c;官方推…

腾讯云 EdgeOne 产品分析与免费套餐体验指南

本文围绕腾讯云 EdgeOne 展开&#xff0c;全方位介绍它的核心能力、免费套餐内容&#xff0c;以及如何快速上手、监控和排查常见问题&#xff0c;帮助个人开发者和中小企业在不产生额外成本的前提下体验高性能的边缘加速与安全防护。 一、产品概述 EdgeOne 定位 一体化云服务平…

npm ERR! Unsupported URL Type “workspace:“: workspace:./lib

如下 npm install npm ERR! code EUNSUPPORTEDPROTOCOL npm ERR! Unsupported URL Type "workspace:": workspace:./libnpm ERR! A complete log of this run can be found in: D:\IDEA\nodejs\node_cache\_logs\2025-08-06T08_21_32_592Z-debug-0.log原因及解决 pac…

微积分: 变化与累积

微积分,这门研究变化与累积的数学分支,其核心思想竟与东方哲学中"易"的概念不谋而合。《易经》有云:“易有太极,是生两仪”,而微积分正是通过"微分"与"积分"这对辩证统一的操作,揭示了世间万物变化与永恒的奥秘。 #mermaid-svg-UjO6qqMm0h…

web-vue工作流程

接续bmcweb流程。 当登录openbmc web页面后,浏览器会根据index.html中的js文件中的routes信息,自动获取信息,比如当前的网络设置信息、Datetime时区时间信息等。 以获取网络配置信息为例: 浏览器从app.js获取到settins->network的route:”/settings/network”,加载对应…

全球化2.0 | 泰国IT服务商携手云轴科技ZStack重塑云租赁新生态

在全球数字化转型不断加速的今天&#xff0c;泰国企业对于高质量云服务的需求日益旺盛。作为深耕本地市场逾二十年的行业领先IT服务商&#xff0c;泰国IT服务商不仅覆盖了IT系统、软件、硬件及网络等多个领域&#xff0c;还持续引领当地技术服务创新。近期&#xff0c;该泰国IT…

一文搞懂Hive临时表操作秘籍

Hive 临时表&#xff1a;数据处理的得力助手 在大数据处理的广阔领域中&#xff0c;Hive 凭借其强大的数据仓库功能&#xff0c;成为了众多数据分析师和开发者的得力工具。Hive 提供了类似 SQL 的查询语言 HiveQL&#xff0c;让我们能够方便地对存储在 Hadoop 分布式文件系统&a…

瞬态吸收光谱仪的基本原理

目录 1. 基态与激发态 2. 时间上的动力学信息 3. pump-probe探测技术 4. 时间延迟和同一光源 5. 延时线和OPA 6. 差分信号 7. 斩波器 原视频链接&#xff1a;瞬态吸收光谱仪的基本原理_哔哩哔哩_bilibili 1. 基态与激发态 当光照射在物质上时&#xff0c;组成物质的微观…

迭代器与生成器:Python 中的高效数据遍历机制

一、迭代器和生成器的基本概念 1. 迭代器的定义和工作原理 &#xff08;1&#xff09;迭代器的概念 迭代器&#xff08;Iterator&#xff09; 是 Python 中一种支持逐个访问元素的对象&#xff0c;它遵循 迭代器协议&#xff08;Iterator Protocol&#xff09;&#xff0c;即实…

Java 发送 HTTP POST请求教程

Java 发送 HTTP POST 请求的方法使用 HttpURLConnection&#xff08;原生 Java 支持&#xff09; 创建一个 HttpURLConnection 对象&#xff0c;设置请求方法为 POST&#xff0c;并写入请求体数据。以下是一个简单示例&#xff1a;import java.io.OutputStream; import java.ne…

计算机英语详细总结

计算机英语作为信息技术领域的专用语言&#xff0c;融合了专业术语、缩写、行业表达及技术文档规范&#xff0c;是学习编程、从事 IT 工作的核心工具。以下从核心分类、应用场景、学习方法三方面详细梳理&#xff1a;一、核心术语分类与高频词汇1. 编程语言与语法基础基础概念&…

「日拱一码」045 机器学习-因果发现算法

目录 基于约束的方法 (Constraint-based) 基于评分的方法 (Score-based) 基于函数因果模型的方法 (Functional Causal Models) 基于梯度的方法 (Gradient-based) 因果发现是机器学习中一个重要的研究方向&#xff0c;它旨在从观测数据中推断变量之间的因果关系 基于约束的…

S7-1200 串行通信介绍

S7-1200 串行通信S7-1200支持的串行通讯方式点对点&#xff08;PtP&#xff09;通信Modbus 主从通信USS 通信名称CM 1241 RS232CM 1241 RS422/485CB 1241 RS485订货号6ES7241-1AH32-0XB06ES7241-1CH32-0XB06ES7241-1CH30-1XB0通讯口类型RS232RS422/RS485RS485波特率(bps)300 ;6…

达梦包含OR条件的SQL特定优化----INJECT-HINT优化方法

Time:2025/08/07Author:skatexg应用迭代发版须执行如下动作 1、按目标需求全面压力测试&#xff0c;优化潜在慢SQL或设置特殊优化参数(如&#xff1a;OPTIMIZER_OR_NBEXP) 2、达梦数据库有数据导入&#xff0c;必须收集统计信息达梦使用SF_INJECT_HINT系统函数对指定SQL增加HIN…

JSqlParser学习笔记 快速使用JSqlParser

文章目录前言本章节源码官方文档信息认识JSqlParserHow it works? 它是如何工作的&#xff1f;知识点关于statement实际应用场景引入依赖Parser 解析SQL解析sql语句解析sql区分sql类型分析增删改查语句查询语句认识PlainSelect示范新增语句了解Insert常用方法示范更新语句删除…

Godot ------ 中级人物血条制作01

Godot ------ 中级人物血条制作 引言 正文 传统血条制作 方格血条制作 传奇,暗黑破环神类血条显示 引言 在此之前,我们分四篇介绍了 Godot 中人物血条的制作,但是我们用到的都是比较基础的节点 ProgressBar,本文我们将介绍另外一种相对高级的节点 TextureProgressBar。 正…