使用eframe/egui从磁盘动态加载和显示图像

问题描述 投票:0回答:1

我正在尝试使用 Rust 中的 eframe/egui 实现我自己的图像查看器。 但是我似乎无法使用文件路径加载和显示图像。

我希望程序能够像这样工作:

  1. 选择目录

  2. 从目录中获取每个文件

  3. 显示最新图像

  4. 使用按钮单击/循环浏览图像

目前我被困在第3点XD

fn main() -> Result<(), eframe::Error>{
    env_logger::init();
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
        ..Default::default()
    };
    eframe::run_native(
        "Image Viewer",
        options,
        Box::new(
            |cc| {
               egui_extras::install_image_loaders(&cc.egui_ctx);
                Box::<ImageViewer>::default()
            }
        )
    )
}

#[derive(Default)]
struct ImageViewer {
    directory_path: Option<String>,
    images: Vec<String>,
    has_images: bool,
    current_image: i32
}

impl eframe::App for ImageViewer {
    fn update(&mut self, ctx: &Context, frame: &mut Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.vertical_centered_justified(|ui| {
                ui.horizontal_top(|ui| {
                    let path_label = ui.label("Path:");
                    let window_width = ui.available_width();
                    if let Some(directory_path) = &self.directory_path {
                        if ui.add_sized(
                            [window_width, 10.0],
                            egui::Button::new(directory_path)
                        )
                            .labelled_by(path_label.id)
                            .clicked() {
                            if let Some(path) = FileDialog::new().set_directory("/").pick_folder() {
                                self.directory_path = Some(path.display().to_string());
                                self.images = get_image_paths_from_directory(path);
                                self.has_images = self.images.len() > 0;
                                self.current_image = 0;
                            }
                        }
                    } else {
                        if ui.add_sized(
                            [window_width, 10.0],
                            egui::Button::new("No image directory selected")
                        )
                            .labelled_by(path_label.id)
                            .clicked() {
                            if let Some(path) = FileDialog::new().set_directory("/").pick_folder() {
                                self.directory_path = Some(path.display().to_string());
                                self.images = get_image_paths_from_directory(path);
                                self.has_images = self.images.len() > 0;
                                self.current_image = 0;
                            }
                        };
                    }
                });
                ui.vertical_centered_justified(|ui| {
                    if self.has_images {
                        // Load and display image
                    } else {
                        // Show placeholder
                    }
                })
            })
        });
    }
}

// Gets the file paths from a given PathBuf
fn get_image_paths_from_directory(path_buf: PathBuf) -> Vec<String> {
    path_buf
        .read_dir()
        .unwrap()
        .map(|entry| {
            let entry = entry.unwrap();
            let entry_path = entry.path();
            let file_name = entry_path.as_os_str();
            let file_name_as_str = file_name.to_str().unwrap();
            let file_name_as_string = String::from(file_name_as_str);

            file_name_as_string
        })
        .collect::<Vec<String>>()
}

我知道你可以实现这样的图像

ui.add(egui::Image::new(egui::include_image!(image_path)));

但是,您必须在运行程序之前声明 image_path,而且我似乎找不到在执行过程中更改路径的方法(或者如果可能的话)。另外,预先设置变量也无法达到选择目录和浏览其图像的目的。

我还尝试了一些将图像转换为字节并以这种方式加载它的方法,但没有取得积极的结果。

image rust egui eframe
1个回答
1
投票

只需将 URI

file:///path/to/your/file.png
传递给您的
Image::new
调用,它需要任何实现
Into<ImageSource>
的内容,并且有一个
From<String> for ImageSource
的实现将
String
视为 URI:

let file_path = "/path/to/your/file.png";
let image = Image::new(format!("file://{file_path}"));

Ui::image
上的示例确实涵盖了这种情况,并且应该是更好的手册
add(Image)

ui.image("file://assets/ferris.png");
© www.soinside.com 2019 - 2024. All rights reserved.