【rust/egui】(四)看看template的app.rs:update以及组件TopBottomPanelButton

说在前面

  • rust新手,egui没啥找到啥教程,这里自己记录下学习过程
  • 环境:windows11 22H2
  • rust版本:rustc 1.71.1
  • egui版本:0.22.0
  • eframe版本:0.22.0
  • 上一篇:这里

update

  • update实际上还是eframe::App的特征,并非egui的内容。其官方注解如下:
    fn update(&mut self, ctx: &Context, frame: &mut Frame)
    Called each time the UI needs repainting, 
    which may be many times per second.
    
    update函数会在需要重绘ui(或者其他)的时候被调用,一秒可能会调用多次
    (稍微看了下源代码,可能是事件驱动调用?)
  • 我们可以在该函数里加个日志看看调用情况:
    [2023-08-20T07:44:02Z ERROR demo_app::app] update
    [2023-08-20T07:44:02Z ERROR demo_app::app] update
    [2023-08-20T07:44:02Z ERROR demo_app::app] update
    [2023-08-20T07:44:02Z ERROR demo_app::app] update
    [2023-08-20T07:44:02Z ERROR demo_app::app] update
    [2023-08-20T07:44:07Z ERROR demo_app::app] update
    [2023-08-20T07:44:07Z ERROR demo_app::app] update
    
    可以看到,当我们不进行任何操作(鼠标、键盘均不输入)时,是没有任何输出的,当按住任意一个按键后,日志开始疯狂输出,这也印证了事件驱动的猜想。
  • 其他内容本文暂未深入

TopBottomPanel

  • 接下来正式开始接触egui的内容,首先是:

    #[cfg(not(target_arch = "wasm32"))] // 非wasm才有
    egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {// 顶部的panel通常用于菜单栏egui::menu::bar(ui, |ui| {ui.menu_button("File", |ui| {if ui.button("Quit").clicked() {_frame.close();}});});
    });
    
  • 看看这里面是些什么,首先是top(),其实现如下:

    pub fn top(id: impl Into<Id>) -> Self {Self::new(TopBottomSide::Top, id)
    }
    // id需要是全局唯一的, e.g. Id::new("my_top_panel").
    

    参数id:需要实现Into<Id>特征,并且需要全局唯一,那我要是不唯一怎么办,比如把下面的SidePanel也改成一样的:

    egui::SidePanel::left("top_panel")
    

    运行后出现报错 (错误提示还挺全) 在这里插入图片描述

  • 在函数实现中,实际上还是调用的new方法,传入位置的枚举TopBottomSide::Top

  • 当然我们也可以调用bottom()方法,对应枚举TopBottomSide::Bottom
    在这里插入图片描述

  • new方法的实现如下:

    pub fn new(side: TopBottomSide, id: impl Into<Id>) -> Self {Self {side,id: id.into(), // 调用into方法,转为Id类型frame: None,resizable: false, // 下面是一些控制参数show_separator_line: true,default_height: None,height_range: 20.0..=f32::INFINITY,}
    }
    
  • 紧跟top()的是show()方法:

    pub fn show<R>(self,ctx: &Context,add_contents: impl FnOnce(&mut Ui) -> R
    ) -> InnerResponse<R>
    

    参数add_contentsFnOnce闭包,仅执行一次,在我们的应用中,闭包中添加了一个简单的菜单栏:

    // 添加菜单栏
    egui::menu::bar(ui, |ui| {ui.menu_button("File", |ui| {if ui.button("Quit").clicked() {_frame.close();}});
    });
    
  • 注意:上面说的执行一次,是说此次update调用中执行一次

  • 我们继续深入下TopBottomPanel的定义:

    pub struct TopBottomPanel {side: TopBottomSide,id: Id,frame: Option<Frame>,resizable: bool,show_separator_line: bool,default_height: Option<f32>,height_range: RangeInclusive<f32>,
    }
    

    其实是可以修改一些样式的,比如高度:

    egui::TopBottomPanel::top("top_panel").min_height(100.0).show(...
    

    在这里插入图片描述

menu::bar

  • TopBottomPanel中,我们使用bar()函数添加了一个菜单栏,其函数定义如下:
    pub fn bar<R>(ui: &mut Ui,add_contents: impl FnOnce(&mut Ui) -> R
    ) -> InnerResponse<R>
    
    同样使用FnOnce闭包来添加一些额外的元素
  • 菜单栏组件在TopBottomPanel::top中的展示效果最好,当然也可以放在Window中。
    The menu bar goes well in a TopBottomPanel::top, 
    but can also be placed in a Window. In the latter case you may want to wrap it in Frame.
    
    在这里插入图片描述
    放到bottom会盖住菜单(File):
    在这里插入图片描述

menu::menu_button

  • bar()的回调中,我们添加了一个下拉按钮
    pub fn menu_button<R>(ui: &mut Ui,title: impl Into<WidgetText>,add_contents: impl FnOnce(&mut Ui) -> R
    ) -> InnerResponse<Option<R>>
    Construct a top level menu in a menu bar.
    
    似乎menu_button最好包在menu bar
  • 同时也使用了FnOnce闭包添加了一个按钮:
    ui.menu_button("File", |ui| {if ui.button("Quit").clicked() {_frame.close();}
    });
    
  • 其实我们还可以在menu_button中添加一个子menu_button
    ui.menu_button("File", |ui| {if ui.button("Quit").clicked() {_frame.close();}ui.menu_button("QuitMenu", |ui| {if ui.button("Quit").clicked() {_frame.close();}});
    });
    
    效果如图
    在这里插入图片描述
  • 如果menu_button直接放在panel中会怎样呢?
    在这里插入图片描述
    其实也是可以的,只是效果不是很好,对比一下(上图是放在panel中,下图是放在bar中的效果):
    在这里插入图片描述

Ui::button

  • 上面我们已经接触到了文本按钮,其定义如下:
    pub fn button(&mut self, text: impl Into<WidgetText>) -> Response
    
  • 实际上是一个简单的封装函数:
    Button::new(text).ui(self)
    
  • 通常的用法是:
    if ui.button("Click me").clicked() {}
    
  • 现在我们进一步看看Button的定义:
    pub struct Button {text: WidgetText,shortcut_text: WidgetText,wrap: Option<bool>,/// None means default for interactfill: Option<Color32>,stroke: Option<Stroke>,sense: Sense,small: bool,frame: Option<bool>,min_size: Vec2,rounding: Option<Rounding>,image: Option<widgets::Image>,
    }
    
  • 是有一些参数可以设置的,那我们怎样添加一个不一样的按钮呢?
    if ui.add(egui::Button::new("q")// .fill(Color32::GOLD).min_size(egui::Vec2 { x: 20.0, y: 100.0 })).clicked()
    {_frame.close();
    }
    
    在这里插入图片描述
    在这里插入图片描述
  • ui.button()ui.add()返回的都是Response,它可以让我们知道ui元素是否被点击、拖拽,进而做出对应的处理;例如点击事件:
    pub fn clicked(&self) -> bool {self.clicked[PointerButton::Primary as usize]
    }
    
    其大致流程是:鼠标点击事件被eframe捕获,由egui计算与整个ui的交互结果,例如哪些元素被点击到了,点击结果存储到Response.clicked数组中,我们只需访问即可。
    clicked存储了五种点击事件
    pub enum PointerButton {/// The primary mouse button is usually the left one./// 通常是鼠标左键Primary = 0,/// The secondary mouse button is usually the right one,/// and most often used for context menus or other optional things./// 通常是鼠标右键Secondary = 1,/// The tertiary mouse button is usually the middle mouse button (e.g. clicking the scroll wheel)./// 通常是鼠标中键Middle = 2,/// The first extra mouse button on some mice. In web typically corresponds to the Browser back button.Extra1 = 3,/// The second extra mouse button on some mice. In web typically corresponds to the Browser forward button.Extra2 = 4,
    }
    

eframe::Frame::close

  • 调用该函数会通知eframe关闭应用,调用后应用不会立即关闭,而是在该帧结束的时候关闭
  • 同时,如果crate::run_native后面还有代码的话,也会继续执行:
    let ret = eframe::run_native("demo app",native_options,Box::new(|cc| Box::new(demo_app::TemplateApp::new(cc))),
    );log::error!("end");ret
    

参考

  • Button
  • menu_button
  • bar
  • TopBottomPanel
  • update

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

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

相关文章

自研分布式IM-HubuIM RFC草案

HubuIM RFC草案 消息协议设计 基本协议 评估标准 【性能】协议传输效率&#xff0c;尽可能降低端到端的延迟&#xff0c;延迟高于200ms用户侧就会有所感知 【兼容】既要向前兼容也要向后兼容 【存储】减少消息包的大小&#xff0c;降低空间占用率&#xff0c;一个字节在亿…

最新AI系统ChatGPT程序源码/微信公众号/H5端+搭建部署教程+完整知识库

一、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01…

二级MySQL(五)——完整性约束练习

在MYSQL中&#xff0c;通常用来指定一个已有数据库作为当前数据库的语句是【USE】 下列选项中不是MYSQL中常用数据类型的是【VAR】 在MYSQL中&#xff0c;常用【NULL】表示一个字段没有值或缺值 在CREATE TABLE语句中&#xff0c;通常使用【PRIMARY KEY】关键字来指定主键 …

IoT DC3 是一个基于 Spring Cloud 的开源的、分布式的物联网(IoT)平台本地部署步骤

dc3 windows 本地搭建步骤&#xff1a; ​​ 必要软件环境 进入原网页# 务必保证至少需要给 docker 分配&#xff1a;1 核 CPU 以及 4G 以上的运行内存&#xff01; JDK : 推荐使用 Oracle JDK 1.8 或者 OpenJDK8&#xff0c;理论来说其他版本也行&#xff1b; Maven : 推荐…

【视觉SLAM入门】5.2. 2D-3D PNP 3D-3D ICP BA非线性优化方法 数学方法SVD DLT

"养气之学&#xff0c;戒之躁急" 1. 3D-2D PNP1.1 代数法1.1.1 DLT(直接线性变换法)1.1.2. P3P 1.2 优化法BA (Bundle Adjustment)法 2. 3D-3D ICP2.1 代数法2.1.1 SVD方法 2.2 优化(BA)法2.2.2 非线性优化方法 前置事项&#xff1a; 1. 3D-2D PNP 该问题描述为&am…

记录《现有docker中安装spark3.4.1》

基础docker环境中存储hadoop3--方便后续查看 参考&#xff1a; 实践&#xff1a; export JAVA_HOME/opt/apache/jdk1.8.0_333 export SPARK_MASTER_IP192.168.0.220 export SPARK_WORKER_MEMORY4g export SPARK_WORKER_CORES2 export SPARK_EXECUTOR_MEMORY4g export HADOOP_H…

Mongodb两种启动方法

一、命令行启动 1.修改存放数据库的位置 说明&#xff1a;E:\data\mongodb&#xff1b;我在E盘创建的文件夹mongodb mongod --dbpathE:\data\mongodb 2.成功启动 说明&#xff1a;默认端口27017&#xff0c;代表已经启动成功 &#xff0c;并在mongodb自动创建文件 二、配置项…

华为AR路由器 典型配置案例——以太网交换

目录 Eth-Trunk 例&#xff1a;配置三层链路聚合 组网需求 操作步骤 检查配置结果 配置脚本 VLAN 举例&#xff1a;配置基于接口划分VLAN&#xff0c;实现同一VLAN内的互通&#xff08;同设备&#xff09; 组网需求 操作步骤 检查配置结果 配置脚本 举例&#xff…

TCP半连接队列和全连接队列

目录 什么是 TCP 半连接队列和全连接队列&#xff1f; TCP 全连接队列溢出 如何知道应用程序的 TCP 全连接队列大小&#xff1f; 如何模拟 TCP 全连接队列溢出的场景&#xff1f; 全连接队列溢出会发生什么 ? 如何增大全连接队列呢 ? TCP 半连接队列溢出 如何查看 TC…

22款美规奔驰S500升级原厂香氛负离子系统,清香宜人,久闻不腻

奔驰原厂香氛合理性可通过车内空气调节组件营造芳香四溢的怡人氛围。通过更换手套箱内香氛喷雾发生器所用的香水瓶&#xff0c;可轻松选择其他香氛。香氛的浓度和持续时间可调。淡雅的香氛缓缓喷出&#xff0c;并且在关闭后能够立刻散去。车内气味不会永久改变&#xff0c;香氛…

Linux 虚拟机安装 hadoop

目录 1 hadoop下载 2 解压hadoop 3 为 hadoop 文件夹改名 4 给 hadoop 文件夹赋权 5 修改环境变量 6 刷新环境变量 7 在hadoop313目录下创建文件夹data 8 检查文件 9 编辑 ./core-site.xml文件 10 编辑./hadoop-env.sh文件 11 编辑./hdfs-site.xml文件 12 编辑./mapr…

【C++入门到精通】C++入门 —— 模版(template)

阅读导航 前言一、模版的概念二、函数模版1. 函数模板概念2. 函数模板定义格式3. 函数模板的原理4. 函数模版的实例化&#x1f6a9;隐式实例化&#x1f6a9;显式实例化 5. 函数模板的匹配原则 三、类模板1. 类模板的定义格式2. 类模板的实例化 四、非类型模板参数1. 概念2. 定义…

动态规划之路径问题

路径问题 1. 不同路径&#xff08;medium&#xff09;2. 不同路径II&#xff08;medium&#xff09;3. 礼物最大值&#xff08;medium&#xff09;4. 下降路径最小和&#xff08;medium&#xff09;5. 最⼩路径和&#xff08;medium&#xff09;6. 地下城游戏&#xff08;hard&…

图床项目进度(一)——UI首页

1. 前言 前面我不是说了要做一个图床吗&#xff0c;现在在做ui。 我vue水平不够高&#xff0c;大部分参考b站项目照猫画虎。 vue实战后台 我使用ts&#xff0c;vite&#xff0c;vue3进行了重构。 当然&#xff0c;我对这些理解并不深刻&#xff0c;许多代码都是游离于表面&am…

基于决策树(Decision Tree)的乳腺癌诊断

决策树(DecisionTree)学习是以实例为基础的归纳学习算法。算法从--组无序、无规则的事例中推理出决策树表示形式的分类规则,决策树也能表示为多个If-Then规则。一般在决策树中采用“自顶向下、分而治之”的递归方式,将搜索空间分为若千个互不相交的子集,在决策树的内部节点(非叶…

Spring事务和事务传播机制

目录 一. Spring 中事务的实现 1. 编程式事务 2. 声明式事务 3. Transaction 参数的设置 4. Transaction 的隔离级别 5. Transaction 的工作原理 二. Spring 事务传播机制 七种事务传播机制 支持当前事务 不支持当前事务 嵌套事务 一. Spring 中事务的实现 1. 编程式事…

mmdetection基于 PyTorch 的目标检测开源工具箱 入门教程

安装环境 MMDetection 支持在 Linux&#xff0c;Windows 和 macOS 上运行。它需要 Python 3.7 以上&#xff0c;CUDA 9.2 以上和 PyTorch 1.8 及其以上。 1、安装依赖 步骤 0. 从官方网站下载并安装 Miniconda。 步骤 1. 创建并激活一个 conda 环境。 conda create --name…

Docker是什么?详谈它的框架、使用场景、优势

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、什么是 Docker&#xff1f; 二、Docker 的架构 1、Docker客户端 2、Docker守护进程 3、Docker镜像 4、Docker容器 5、Docker…

【业务功能篇76】微服务网关路由predicates断言条件-filters路由转换地址-跨域问题-多级目录树化层级设计-mybatisPlus逻辑删除

业务开发-基础业务-分类管理 启动renren-fast如果出现如下错误 -Djps.track.ap.dependenciesfalse 添加相关配置即可 分类管理 1.后端分类接口 JDK8特性&#xff1a;https://blog.csdn.net/qq_38526573/category_11113126.html 在后端服务中我们需要查询出所有的三级分类信…

汽车摩托车零部件出口管理ERP解决方案

近年来&#xff0c;随着全球经济的发展&#xff0c;人们对交通工具的需求增加&#xff0c;国内汽车、摩托车市场的不断扩大&#xff0c;以及国内制造技术的不断提高&#xff0c;中国汽车、摩托车零部件出口业务迎来了广阔的发展前景&#xff0c;带动了汽车配件和摩托车配件市场…