简体   繁体   English

如何修改由 Rust 闭包捕获的变量?

[英]How can I modify a variable captured by a Rust closure?

I'm trying to make a GUI for a Rust application, and what looked like it would work well for me is imgui-rs .我正在尝试为 Rust 应用程序制作 GUI,看起来对我来说效果很好的是imgui-rs All I want to be able to do is get some input values from the user, and output a changing png.我想要做的就是从用户那里获取一些输入值,然后 output 是一个不断变化的 png。 I had some trouble getting the boilerplate started, but the provided repository has support code that worked well enough for me to get the hello world demo working, but when I tried modifying it to get input and change the display, I ran into ownership issues.我在启动样板时遇到了一些麻烦,但是提供的存储库的支持代码足以让我让 hello world 演示工作,但是当我尝试修改它以获取输入和更改显示时,我遇到了所有权问题。 What I'm trying to do right now is have the user input an image name, then open that file and display it in the GUI.我现在要做的是让用户输入图像名称,然后打开该文件并将其显示在 GUI 中。

Here's what I have right now (excluding the support code linked above):这是我现在拥有的(不包括上面链接的支持代码):

struct State {
    path: ImString,
    has_image: bool,
}
impl Default for State {
    fn default() -> Self {
        Self {
            path: ImString::with_capacity(128),
            has_image: false,
        }
    }
}
fn main() {
    let mut system = imgui_support::init(file!()); // this is from support code
    let mut state = State::default();

    system.main_loop(move |_, ui| {
        Window::new(im_str!("hello world"))
            .size([330.0, 110.0], imgui::Condition::FirstUseEver)
            .position([0f32, 0f32], imgui::Condition::FirstUseEver)
            .build(ui, || {
                ui.input_text(im_str!("File path"), &mut state.path).build();
                if ui.small_button(im_str!("Submit file")) {
                    system.add_img(state.path.to_str()); // try to open file and parse as texture
                }
                ui.separator();
            });
        if state.has_image {
            Window::new(im_str!("Render:"))
                .size([720f32, 720f32], imgui::Condition::FirstUseEver)
                .build(ui, || {
                    imgui::Image::new(TextureId::new(0), [720f32, 720f32]).build(ui);
                });
        }
    });
}

The add_img function, which I added as a method on the System struct, is defined as: add_img function,我作为System结构上的一个方法添加,定义为:

    pub fn add_img(&mut self, path: &str) -> TextureId {
        let textures: &mut Textures<Texture> = &mut self.renderer.textures();
        let res_img = image::open(path);
        match res_img {
            Ok(image) => {
                let image = image.to_rgba8();
                let dimensions = image.dimensions();
                let texture = RawImage2d::from_raw_rgba(image.into_raw(), dimensions);
                let gl_texture = Texture2d::new(self.display.get_context(), texture).unwrap();
                let texture = imgui_glium_renderer::Texture {
                    texture: Rc::new(gl_texture),
                    sampler: SamplerBehavior {
                        magnify_filter: MagnifySamplerFilter::Linear,
                        minify_filter: MinifySamplerFilter::Linear,
                        ..Default::default()
                    },
                };
                textures.insert(texture)
            }
            Err(_) => TextureId::new(usize::MAX),
        }
    }

Right now, I get the error use of moved value system , and no matter how I try to arrange the data, I can't seem to avoid the use-after-move error.现在,我得到了use of moved value system无论我如何尝试排列数据,我似乎都无法避免移动后使用错误。

Is there a better way to organize my code, or perhaps a Rust GUI library that isn't as robust, since I don't need 99% of the imgui features?有没有更好的方法来组织我的代码,或者可能是一个不太健壮的 Rust GUI 库,因为我不需要 99% 的 imgui 功能?

The problem is, that the method main_loop takes ownership of system .问题是,方法main_loop取得了system的所有权。 System will never be available for you afterwards.之后系统将永远无法使用。

A quick fix would be to update the method main_loop to pass renderer and display to the closure.一个快速的解决方法是更新方法main_loop以将rendererdisplay传递给闭包。 Something like this:像这样的东西:

pub fn main_loop<F>(self, mut run_ui: F)
where F: FnMut(&mut bool, &mut Ui, &mut Renderer, &mut glium::Display) + 'static {}

and then when calling run_ui just add renderer and display.然后在调用run_ui时只需添加渲染器并显示。

run_ui(&mut run, &mut ui, &mut renderer, &mut display);

The method add_img should be made a free-standing function and take renderer and display separately, without depending on System.方法add_img应该是独立的 function 和渲染器和显示分开,不依赖于 System.

pub fn add_img(path: &str, renderer: &mut Renderer, display: &mut glium::Display) -> TextureId {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM