代码之家  ›  专栏  ›  技术社区  ›  Calvin Godfrey

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

  •  0
  • Calvin Godfrey  · 技术社区  · 3 年前

    我正在尝试为一个Rust应用程序制作一个GUI,看起来它对我来说很有用的是 imgui-rs support code 这对我来说已经足够让helloworld演示正常工作了,但是当我试图修改它以获取输入并更改显示时,我遇到了所有权问题。我现在要做的是让用户输入一个图像名称,然后打开该文件并在GUI中显示它。

    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);
                    });
            }
        });
    }
    

    这个 add_img 函数,我在 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),
            }
        }
    

    use of moved value system ,并且无论我如何尝试排列数据,我似乎都无法避免移动后的使用错误。

    1 回复  |  直到 3 年前
        1
  •  2
  •   Sören    3 年前

    问题是,这种方法 main_loop system . 以后系统将永远无法为您提供。

    一个快速解决方法是更新方法 通过 renderer display 结束。 像这样:

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

    run_ui 只需添加渲染器和显示。

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

    方法 add_img 应该是一个独立的功能,并采取渲染器和显示分开,而不依赖于系统。

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