You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SDL2 Rust绑定中管理绘图表面?解决白板程序卡顿问题

解决方案:增量绘制优化白板程序性能

核心思路

不再每次清空画布并重绘所有点,而是仅绘制新增的点,同时处理窗口重绘场景(如窗口最小化恢复)时的全量重绘需求。

修改后的代码框架

#[derive(Copy, Clone, PartialEq, Eq)]
struct Center {
    point: Point,
    radius: i32,
}

fn main() {
//...
    let mut canvas = window.into_canvas().build().unwrap();
    let mut points: Vec<Center> = Vec::new();
    // 记录上一次绘制完成的点数量,用于增量绘制
    let mut last_drawn_count = 0;

    // 初始化:先绘制白色背景,确保初始缓冲区是正确的
    canvas.set_draw_color(Color::RGB(255, 255, 255));
    canvas.clear();
    canvas.present();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                // 处理退出事件
                Event::Quit { .. } => break 'running,
                // 处理窗口重绘事件:需要重新全量绘制所有内容
                Event::Window { win_event: WindowEvent::Exposed, .. } => {
                    canvas.set_draw_color(Color::RGB(255, 255, 255));
                    canvas.clear();
                    canvas.set_draw_color(Color::RGB(0, 0, 0));
                    draw_centers(&mut canvas, &points);
                    last_drawn_count = points.len();
                    canvas.present();
                }
                Event::MouseMotion {
                    x, y, mousestate, ..
                } => {
                    // 鼠标按下时添加新点
                    if mousestate.is_pressed(MouseButton::Left) {
                        points.push(Center {
                            point: Point::new(x, y),
                            radius: 2, // 示例半径
                        });
                    }
                }
                // 其他事件处理...
                _ => {}
            }
        }

        // 增量绘制新增的点
        if last_drawn_count < points.len() {
            let new_points = &points[last_drawn_count..];
            canvas.set_draw_color(Color::RGB(0, 0, 0));
            draw_centers(&mut canvas, new_points);
            last_drawn_count = points.len();
        }

        canvas.present();
    }
}

关键细节说明

  1. 初始背景绘制:程序启动时先绘制一次白色背景并present,确保缓冲区中保存了正确的背景内容,后续无需重复清空。
  2. 增量绘制逻辑:通过last_drawn_count记录已绘制的点数量,每次循环只绘制新增的点(从last_drawn_count到当前points长度的部分),避免全量重绘。
  3. 窗口重绘处理:当窗口收到Exposed事件(如被遮挡后恢复、窗口大小调整),需要重新清空画布并全量绘制所有点,否则窗口内容会丢失。

为什么直接去掉canvas.clear()会变黑?

SDL的Canvas默认使用双缓冲机制:每次present()会交换前台(显示)和后台(绘制)缓冲区。如果不执行clear(),后台缓冲区的内容是未初始化的(通常为黑色),交换后前台就会显示黑色。初始时先绘制背景并present,就能让后台缓冲区保留正确的背景内容,后续增量绘制时直接在这个基础上添加新点即可。

内容的提问来源于stack exchange,提问作者Manuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:02:47