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

说在前面

  • 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);
    });
    
    结果如下
    【rust/egui】(九)使用painter绘制一些图形—基本使用_第1张图片

绝对定位

  • 虽然我们绘制出了一个矩形,但是它显示的位置却有些奇怪,这是因为我们使用的是绝对定位
  • 我们使用矩形的左上、右下两个点来确定该矩形,如下图(10,100)、(110,300),其宽100高200:
    【rust/egui】(九)使用painter绘制一些图形—基本使用_第2张图片
  • 如果想要在我们的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);
    });
    
    【rust/egui】(九)使用painter绘制一些图形—基本使用_第3张图片
  • 在转换后,我们的矩形为:
    【rust/egui】(九)使用painter绘制一些图形—基本使用_第4张图片

拖拽

  • 在添加矩形后,我们可以对其进行拖拽:
    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

你可能感兴趣的:(Rust,rust,开发语言,后端)