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

如何在Egui中创建指定屏幕坐标范围的ScrollArea?

解决Egui中指定位置ScrollArea文本错位问题

我需要创建一个边界为指定屏幕坐标(x,y)至(z,w)的ScrollArea,类似HTML中固定宽高、可放置在屏幕任意位置的<div>。目前绘制的紫色容器边界范围正确,但ScrollArea内的文本却在容器外部;期望文本位于容器内,且能基于容器边界滚动。

当前代码片段:

let rect = Rect::from_min_max(pos2(80.0, 80.0), pos2(280.0, 280.0));
let frame = egui::Frame::none()
    .fill(Color32::from_rgb(232, 12, 232))
    .paint(rect);

ui.painter().add(frame);

egui::ScrollArea::vertical()
    .max_height(280.0 - 80.0)
    .max_width(280.0 - 80.0)
    .show(ui, |ui| {
        ui.add(Label::new("long text".repeat(99)));
    });

完整代码:

use eframe::egui::{self, *};

fn main() {
    let native_options = eframe::NativeOptions::default();

    eframe::run_native(
        "Arbitrary Scroll",
        native_options,
        Box::new(|_| Box::new(MyEguiApp)),
    )
    .unwrap();
}

struct MyEguiApp;

impl eframe::App for MyEguiApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            let rect = Rect::from_min_max(pos2(80.0, 80.0), pos2(280.0, 280.0));
            let frame = egui::Frame::none()
                .fill(Color32::from_rgb(232, 12, 232))
                .paint(rect);

            ui.painter().add(frame);

            egui::ScrollArea::vertical()
                .max_height(280.0 - 80.0)
                .max_width(280.0 - 80.0)
                .show(ui, |ui| {
                    ui.add(Label::new("long text".repeat(99)));
                });
        });
    }
}

问题原因

你直接通过ui.painter()绘制的紫色容器是独立的图形操作,和ScrollArea的布局逻辑没有关联。ScrollArea默认遵循CentralPanel的布局流,从面板左上角开始渲染,因此和你手动绘制的紫色框位置错位。

两种可行解决方案

方案一:用ui.allocate_rect约束ScrollArea到指定区域

通过ui.allocate_rect在UI布局中预留指定的矩形空间,再让ScrollArea填充这个空间,确保文本和容器对齐:

impl eframe::App for MyEguiApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            let rect = Rect::from_min_max(pos2(80.0, 80.0), pos2(280.0, 280.0));
            
            // 在UI布局中分配指定矩形区域
            let response = ui.allocate_rect(rect, Sense::hover());
            
            // 绘制紫色背景填充该区域
            ui.painter().rect_filled(rect, 0.0, Color32::from_rgb(232, 12, 232));
            
            // 在分配好的区域内创建ScrollArea
            egui::ScrollArea::vertical()
                .show_inside(ui, response.rect, |ui| {
                    ui.add(Label::new("long text".repeat(99)));
                });
        });
    }
}

方案二:用egui::Area创建固定位置容器(更贴近HTML固定div)

egui::Area专门用于创建可自由放置的UI容器,设置固定位置和尺寸后,内部的ScrollArea会自动约束在容器内:

impl eframe::App for MyEguiApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |_| {
            // 创建固定位置的Area容器
            egui::Area::new("fixed_scroll_container")
                .fixed_pos(pos2(80.0, 80.0)) // 容器左上角坐标
                .fixed_size(vec2(200.0, 200.0)) // 容器宽高(280-80)
                .show(ctx, |ui| {
                    // 设置容器背景色为紫色
                    ui.style_mut().visuals.panel_fill = Color32::from_rgb(232, 12, 232);
                    
                    // 在容器内添加ScrollArea
                    egui::ScrollArea::vertical()
                        .show(ui, |ui| {
                            ui.add(Label::new("long text".repeat(99)));
                        });
                });
        });
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:44:50