【rust/egui】(九)使用painter绘制一些图形—基本使用

news2024/10/11 14:24:37

说在前面

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

painter

  • 定义
    pub struct Painter {
        /// Source of fonts and destination of shapes
        ctx: Context,
    
        /// Where we paint
        layer_id: LayerId,
    
        /// Everything painted in this [`Painter`] will be clipped against this.
        /// This means nothing outside of this rectangle will be visible on screen.
        clip_rect: Rect,
    
        /// If set, all shapes will have their colors modified to be closer to this.
        /// This is used to implement grayed out interfaces.
        fade_to_color: Option<Color32>,
    }
    
  • 我们可以使用painter来添加一个简单的矩形:
    egui::CentralPanel::default().show(ctx, |ui| {
    	// 从ui中指定一块区域
        let response =
        ui.allocate_rect(ui.available_rect_before_wrap(), egui::Sense::hover());
    	// 添加一个空Shape
        let shape = ui.painter().add(egui::Shape::Noop);
    	// 定义圆角大小
        let rounding = egui::Rounding::same(4.0);
        // 定义要绘制的矩形大小及位置
        let body_rect = egui::Rect::from_min_size(egui::pos2(10.0, 100.0), egui::vec2(100.0, 200.0));
        // 添加一个矩形
        let body = egui::Shape::Rect(egui::epaint::RectShape {
            rect: body_rect,
            rounding: rounding,
            fill: color_from_hex("#3f3f3f").unwrap(),
            stroke: egui::Stroke::NONE,
        });
    	// 绘制
        ui.painter().set(shape, body);
    });
    
    结果如下
    在这里插入图片描述

绝对定位

  • 虽然我们绘制出了一个矩形,但是它显示的位置却有些奇怪,这是因为我们使用的是绝对定位
  • 我们使用矩形的左上、右下两个点来确定该矩形,如下图(10,100)、(110,300),其宽100高200:
    在这里插入图片描述
  • 如果想要在我们的CentralPanel中绘制,需要进行转换:
    egui::CentralPanel::default().show(ctx, |ui| {
        let response = ui.allocate_rect(ui.available_rect_before_wrap(), egui::Sense::hover());
    	// 定义转换
        let to_screen = egui::emath::RectTransform::from_to(
            egui::Rect::from_min_size(egui::Pos2::ZERO, response.rect.size()),
            response.rect,
        );
    
        let shape = ui.painter().add(egui::Shape::Noop);
    
        let rounding_radius = 4.0;
        let rounding = egui::Rounding::same(rounding_radius);
        let mut body_rect =
            egui::Rect::from_min_size(egui::pos2(10.0, 100.0), egui::vec2(100.0, 200.0));
    
        // 进行转换
        body_rect = to_screen.transform_rect(body_rect);
        let body = egui::Shape::Rect(egui::epaint::RectShape {
            rect: body_rect,
            rounding: rounding,
            fill: color_from_hex("#3f3f3f").unwrap(),
            stroke: egui::Stroke::NONE,
        });
    
        ui.painter().set(shape, body);
    });
    
    在这里插入图片描述
  • 在转换后,我们的矩形为:
    在这里插入图片描述

拖拽

  • 在添加矩形后,我们可以对其进行拖拽:
    egui::CentralPanel::default().show(ctx, |ui| {
        let response = ui.allocate_rect(ui.max_rect(), egui::Sense::hover());
        let to_screen = egui::emath::RectTransform::from_to(
            egui::Rect::from_min_size(egui::Pos2::ZERO, response.rect.size()),
            response.rect,
        );
        let shape = ui.painter().add(egui::Shape::Noop);
        let rounding_radius = 4.0;
        let rounding = egui::Rounding::same(rounding_radius);
        let mut body_rect = egui::Rect::from_min_size(
            egui::Pos2 { x: 10.0, y: 100.0 },
            egui::vec2(100.0, 200.0),
        );
        body_rect = to_screen.transform_rect(body_rect);
        // 添加拖拽事件
        let window_response = ui.interact(
            body_rect,
            egui::Id::new((1, "window")),
            egui::Sense::click_and_drag(),
        );
        // 计算拖拽偏移量
        let drag_delta = window_response.drag_delta();
        if drag_delta.length_sq() > 0.0 {
        	// 移动矩形
            body_rect = body_rect.translate(drag_delta);
        }
        let body = egui::Shape::Rect(egui::epaint::RectShape {
            rect: body_rect,
            rounding: rounding,
            fill: color_from_hex("#3f3f3f").unwrap(),
            stroke: egui::Stroke::NONE,
        });
        ui.painter().set(shape, body);
    });
    
    在这里插入图片描述
    但是好像拖不动,这是因为每次update的时候,我们定义的矩形位置都是固定的:
    let mut body_rect = egui::Rect::from_min_size(
            egui::Pos2 { x: 10.0, y: 100.0 },
            egui::vec2(100.0, 200.0),
        );
    
    因此我们需要记下上一次的位置:
    pub struct TemplateApp {
    	// ..
        // pos
        #[serde(skip)]
        rect_pos: egui::Pos2,
    }
    
    然后在创建矩形的时候使用上一次的位置:
    egui::CentralPanel::default().show(ctx, |ui| {
        let response = ui.allocate_rect(ui.max_rect(), egui::Sense::hover());
        let to_screen = egui::emath::RectTransform::from_to(
            egui::Rect::from_min_size(egui::Pos2::ZERO, response.rect.size()),
            response.rect,
        );
        let shape = ui.painter().add(egui::Shape::Noop);
        let rounding_radius = 4.0;
        let rounding = egui::Rounding::same(rounding_radius);
        let mut body_rect = egui::Rect::from_min_size(
            self.rect_pos,
            egui::vec2(100.0, 200.0),
        );
        body_rect = to_screen.transform_rect(body_rect);
        // 添加拖拽事件
        let window_response = ui.interact(
            body_rect,
            egui::Id::new((1, "window")),
            egui::Sense::click_and_drag(),
        );
        // 计算拖拽偏移量
        let drag_delta = window_response.drag_delta();
        if drag_delta.length_sq() > 0.0 {
        	// 移动矩形
            body_rect = body_rect.translate(drag_delta);
            // 改变初始位置
            self.rect_pos = self.rect_pos + drag_delta;
        }
        let body = egui::Shape::Rect(egui::epaint::RectShape {
            rect: body_rect,
            rounding: rounding,
            fill: color_from_hex("#3f3f3f").unwrap(),
            stroke: egui::Stroke::NONE,
        });
        ui.painter().set(shape, body);
    });
    
    在这里插入图片描述

参考

  • painter
  • paint_bezier

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

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

相关文章

领域驱动设计:DDD分层架构

文章目录 DDD 分层架构DDD 分层架构最重要的原则DDD 分层架构推动架构演进三层架构如何演进到 DDD 分层架构 微服务架构模型有好多种&#xff0c;例如整洁架构、CQRS 和六边形架构等等。每种架构模式虽然提出的时代和背景不同&#xff0c;但其核心理念都是为了设计出“高内聚低…

gpt测试

已知a地一石头售价80&#xff0c;b地售价112&#xff0c;小明初始资金8000&#xff0c;在a地全仓购入后&#xff0c;去b地出售&#xff0c;然后小明又回到a地&#xff0c;再次全仓购入然后去b地出售&#xff0c;这样继续出售10次后&#xff0c;小明有多少钱&#xff1f;石头是不…

Java中wait和notify详解

线程的调度是无序的&#xff0c;随机的&#xff0c;但是也是有一定的需求场景&#xff0c;希望能够有序执行&#xff0c;join算是一种控制顺序的方式&#xff08;功能有限&#xff09;——》一个线程执行完&#xff0c;才能执行另一个线程&#xff01; 本文主要讲解的&#xf…

C++---类和对象

这里写目录标题 封装简介语法二级目录二级目录二级目录二级目录二级目录二级目录二级目录二级目录二级目录二级目录二级目录二级目录二级目录 封装 简介语法 类 &#xff1a;抽象的 共性的 对象&#xff1a;实例化的 具体的 个性的 封装 就是把属性和行为放在一起 加一些访问权…

CCRC-PIPA个人信息保护评估师

个人信息保护评估师 (Personal InformationProtec-tion Assessor&#xff0c;简称 “PIPA”) 是由中国网络安全审查技术与认证中心(简称CCRC) 推出的面向个人信息保护领域的培训认证。CCRC-PIPA课程以《个人信息保护法》、法规、部门规章、相关国家标准和行业最佳实践为基础&am…

代理IP在海外SEO优化中有哪些关键作用?

代理IP在海外SEO优化业务中的应用越来越受到企业的重视。它为企业提供了大量不同地区的IP地址&#xff0c;帮助企业模拟不同地区、不同设备的用户行为&#xff0c;有助于更准确地了解当地的搜索引擎规则和优化策略&#xff0c;更好地评估网站的排名和流量。 一、代理IP的优势 …

【Stable Diffusion XL】huggingface diffusers 官方教程解读

文章目录 01 TutorialDeconstruct a basic pipelineDeconstruct the Stable Diffusion pipelineAutopipelineTrain a diffusion model 相关链接&#xff1a; GitHub&#xff1a; https://github.com/huggingface/diffusers 官方教程&#xff1a;https://huggingface.co/docs/di…

第2章_瑞萨MCU零基础入门系列教程之面向过程与面向对象

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

thinkphp6 入门(6)--中间件是什么 怎么用

一、什么是中间件&#xff1f; 当客户端发送请求至服务器时&#xff0c;HTTP请求会经过多个中间件&#xff0c;最后返回响应给客户端。中间件可以 在请求到达目标控制器或动作之前对请求进行操作 可以在响应离开目标控制器或动作之前对响应进行操作 二、中间件的作用 我们可…

【Python】conda虚拟环境下使用pyinstaller打包程序为exe

文章目录 一、为什么要用conda虚拟环境二、pyinstaller用法2.1 安装 PyInstaller2.2 基本用法打包一个 Python 脚本2.21 打包一个 Python 项目2.22 打包选项 2.3 打包依赖项2.31 导出依赖项列表2.32 配置依赖项 2.4 自定义打包选项2.5 打包完成后的文件2.6 注意事项 三、打包示…

RabbitMQ 知识点解读

1、AMQP 协议 1.1、AMQP 生产者的流转过程 当客户端与Broker 建立连接的时候&#xff0c;会调用factory .newConnection 方法&#xff0c;这个方法会进一步封装成Protocol Header 0-9-1 的报文头发送给Broker &#xff0c;以此通知Broker 本次交互采用的是AMQPO-9-1 协议&…

文件上传漏洞案例

目录 1.案例一 1&#xff09;案例源码 2&#xff09;创建web.php文件 3&#xff09;使用抓包软件 2.案例二 1&#xff09;案例代码 2&#xff09; 案例分析 3&#xff09;copy命令生成图片马 4&#xff09;上传图片马到服务器 5&#xff09;解析 文件图片 3.案例三 …

Error running ‘xxx‘: Command line is too long. Shorten command line for xxxx

完整报错信息&#xff1a;Error running ArticleFreemarkerTest.test: Command line is too long. Shorten command line for ArticleFreemarkerTest.test or also for JUnit default configuration. 翻译为运行“ArticleFreemarkerTest.test”时出错&#xff0c;命令行太长。…

计网第四章(网络层)(八)

在第七节&#xff08;计网第四章&#xff08;网络层&#xff09;&#xff08;七&#xff09;_永无魇足的博客-CSDN博客&#xff09;我们总结了路由信息协议RIP。在最后我们提到了RIP协议有坏消息传的慢的问题&#xff0c;这是距离向量算法的本质决定的&#xff0c;所以这种问题…

成都青溪电商:抖店精选联盟怎么绑定?

随着抖音平台的快速发展&#xff0c;越来越多的商家希望利用抖音的流量红利来实现品牌曝光和销量增长。抖音精选联盟作为抖音平台的重要合作计划&#xff0c;为商家提供了更多的机会和资源支持。下面将详细介绍如何绑定抖店精选联盟并讨论解绑情况。 1.绑定抖店选定联盟 满足入…

蓝桥杯官网练习题(数字三角形)

题目描述 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径&#xff0c;把路径上面的数加起来可以得到一个和&#xff0c;你的任务就是找到最大的和。 路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外&a…

AlwaysUp10.5.0.93安装和使用说明

安装包 安装 解压 双击exe 点击完成&#xff0c;完成安装 安装完成自动启动程序

基于串口的BLE模组CC2640R2使用总结

之前写过蓝牙控制芯片nRF52832的一篇概述&#xff0c;里面主要记录了蓝牙的分层结构&#xff0c;需要的话可参考&#xff1a;nRF52832蓝牙概述_路溪非溪的博客-CSDN博客 这篇文章记录的是蓝牙模组的基本使用。 二者有何区别呢&#xff1f; nRF52832是一款基于蓝牙的主控芯片…

QUIC协议科普导入(一)

一&#xff1a;QUIC协议导入 QUIC是一个通用的传输层网络协议&#xff0c;最初由Google的Jim Roskind设计&#xff0c;2012年实现并部署&#xff0c;2013年随着实验范围的扩大而公开发布&#xff0c;并向IETF描述。虽然长期处于互联网草案阶段&#xff0c;但在从Chrome浏览器到…

【考研数学】高等数学第五模块 —— 级数(3,傅里叶级数)

系列文章 【考研数学】高等数学第五模块 —— 级数&#xff08;1&#xff0c;常数项级数&#xff09; 【考研数学】高等数学第五模块 —— 级数&#xff08;2&#xff0c;幂级数&#xff09; 文章目录 引言三、傅里叶级数3.1 周期为 2 π 2\pi 2π 的函数的傅里叶级数3.2 定…