emilk / egui

egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native
https://www.egui.rs/
Apache License 2.0
21.55k stars 1.56k forks source link

ScrollArea contents briefly escape it when it becomes larger #4742

Closed e00E closed 1 week ago

e00E commented 2 months ago

I have content inside a ScrollArea. When the content's size changes and goes from fitting into the area to no longer fitting, then for a split second the content escapes the ScrollArea. After the split second the content is correctly limited to the area and can be scrolled.

I would expect the content to not appear out of bounds for the split second. I realize there are some layout limitations with egui's design. I feel this is a bug because the available size of the area is known at all times. I do not see why in principle there has to be a moment (one frame?) of bad layout.

Below is a minimal reproduction. The program displays a label inside a fixed size scroll area. When it starts, the label fits and there is no need to scroll. When you click the button, the amount of text changes so that it no longer fits into the scroll area and scrolling is needed.

use eframe::Frame;
use egui::{Context, ScrollArea};

fn main() -> eframe::Result<()> {
    let mut lines: usize = 1;

    let run = move |c: &Context, _: &mut Frame| {
        let text = "aaaa\n".repeat(lines);

        egui::CentralPanel::default().show(c, |ui| {
            ui.horizontal(|ui| {
                ui.allocate_ui((50., 50.).into(), |ui| {
                    ScrollArea::both()
                        .auto_shrink(false)
                        .show(ui, |ui| ui.label(text));
                });

                if ui.button("button").clicked() {
                    if lines == 10 {
                        lines = 1;
                    } else {
                        lines = 10;
                    }
                };
            });
        });
    };

    let options = eframe::NativeOptions::default();
    eframe::run_simple_native("", options, run)
}

Here are screenshots displaying the bug.

Before you press the button. There is no bug. 1 After you press the button, for a split second you can see the bug. The text exceeds the area. If I had more content below, the text would be rendered on top of it. 2 After the split second. There is no bug. 3

emilk commented 2 months ago

This should ineed be fixable. The clip rect is probably not set correctly when the ScrollArea believes (based on sizes from previous frame) that it won't need to clip.