表单如何自动添加到窗口中?

How is Form automatically added to the Window?

提问人:rnso 提问时间:4/14/2023 最后编辑:rnso 更新时间:4/14/2023 访问量:64

问:

我正在尝试学习 Rust 和 Fltk gui 库。我在这里看到了一个小的 gui 应用程序示例,它运行良好。以下是 fn:main

fn main() {
    let     a    = app::App::default().with_scheme(app::Scheme::Gtk);
    let mut win  = window::Window::default().with_size(500, 300);
    let mut form = Form::default();
        
    form.register_default_callback();
    win.end();
    win.make_resizable(true);
    win.show();
    win.resize_callback(move |_, _, _, w, h| form.resize(0, 0, w, h));

    a.run().unwrap();
}

我在这里看到表单没有显式添加到窗口中。formwin

是在程序上半部分定义的结构:Form

struct Form {
    grid      : Grid,
    name      : input::Input,
    age       : input::IntInput,
    occupation: input::Input,
    btn       : button::Button,
}

impl Form {

    pub fn default() -> Self {
        let mut grid = Grid::default_fill();
        grid.set_layout(10, 5); // construct a new grid

        let name       = input::Input::default();
        let age        = input::IntInput::default();
        let occupation = input::Input::default();
        let btn        = button::Button::default().with_label("Submit");

        let mut g = Self {
            grid,
            name,
            age,
            occupation,
            btn,
        };
        g.fill();
        g
    }

    fn fill(&mut self) {
        let grid = &mut self.grid;
        grid.debug(false); // set to true to see cell outlines
        
        let mut title = frame::Frame::default().with_label("Employee Form");
        title.set_frame(enums::FrameType::FlatBox);
        title.set_color(enums::Color::Red);
        title.set_label_color(enums::Color::White);
        grid.insert(
            // insert widgets
            &mut title, 0, 1..4
        );

        grid.insert(&mut frame::Frame::default().with_label("Name"), 2, 1);
        grid.insert(&mut self.name, 2, 3);

        grid.insert(&mut frame::Frame::default().with_label("Age"), 4, 1);
        grid.insert(&mut self.age, 4, 3);

        grid.insert(&mut frame::Frame::default().with_label("Occupation"), 6, 1);
        grid.insert(&mut self.occupation, 6, 3);

        grid.insert(&mut self.btn, 8, 2);
    }

    fn register_default_callback(&mut self) {
        self.btn.set_callback({
            let name       = self.name.clone();
            let age        = self.age.clone();
            let occupation = self.occupation.clone();
            move |_| {
                println!("Name: {}", name.value());
                println!("Age: {}", age.value());
                println!("Occupation: {}", occupation.value());
            }
        });
    }

    pub fn resize(&mut self, x: i32, y: i32, w: i32, h: i32) {
        self.grid.resize(x, y, w, h); // determine how it's resized
    }
}

只有同时具有以下两个的行:winform

win.resize_callback(move |_, _, _, w, h| form.resize(0, 0, w, h));

但是,即使删除此行,应用程序仍可工作。

如何自动显示在窗口中?Form

迹斑斑 FLTK

评论

0赞 rnso 4/14/2023
是在程序的上半部分定义的结构。我在上面的问题中已经澄清了这一点。Form

答:

1赞 eten 4/14/2023 #1

这是因为 Form 实际上并不是添加到窗口中的小部件,而是在 Form::d efault 中调用 Grid::d efault_fill,然后将其添加到窗口中。

1赞 Jmb 4/14/2023 #2

这是因为 FLTK 的工作方式。当您创建一个容器(如 )时,之后创建的所有小部件都会自动添加到此容器中,直到您调用其方法。winend

有关小部件的更多详细信息,请参阅本书Group

评论

0赞 Dai 4/14/2023
这听起来像是设计 API 的最糟糕的方式 - 我假设它通过使用 thread-local-storage 来保存对当前环境上下文或环境主题的任何全局可访问的引用......或者它甚至不是线程安全的?
0赞 Jmb 4/14/2023
@Dai我同意糟糕的设计,但这就是底层C++库的工作方式。我不知道它是否是线程安全的,但可能不是(大多数 GUI 库不喜欢从多个线程更改小部件)。
0赞 Jmb 4/14/2023
@Dai还记得 FLTK 已经有 25 年的历史了(第一次提交可以追溯到 1998 年 10 月,在 458 个文件中导入了 61_000 行代码,因此 FLTK 显然要老得多),今天看起来是一个坏主意,当时可能有不同的看法。