Rust Iced를 사용한 간단한 이미지 뷰어

25491 단어 Rustguitech
Iced는 Rust의 GUI Pack이 아직 버전을 결정하지 않은 상태에서 선택 사항으로 사용됩니다.
https://github.com/hecrj/iced
아이스드는 다른 GUI 크레인과 마찬가지로 기능상으로는 턱없이 부족하지만, 어쨌든 간단한 GUI를 원할 때는 사용할 수 있는 느낌이다.
개발은 꾸준히 추진되고 있으며 며칠 전에는 버전이 0.3으로 올랐다.
그래서 이번에는 버전 업그레이드와 무관한 간단한 이미지 뷰어를 만들었습니다.그림% 1개의 캡션을 편집했습니다.

자신의 환경은 다음과 같다.아이스드가 크로스 플랫폼인 것 같아서 맥과 리눅스도 괜찮을 것 같아요.
  • Windows 10
  • Rust 1.50.0
  • 또한 Iced의 기본 섹션에 대해 읽어들이는 동안 사용한 글이 발견되었으니 해당 내용을 참조하십시오.

    징그러운 부분


    이번에는 주로 파일의 드래그 처리와 이미지 디스플레이를 테스트합니다.
    파일 드래그 이벤트 같은 경우 iced의 창고examplesevents를 참조하십시오.
    https://github.com/hecrj/iced/tree/master/examples/events
    구축해 보면 조작에 따라 어떤 사건이 일어날지 알 수 있다.또한 이번 원본 파일은 단지 이것을 바탕으로 디스플레이 처리를 더한 것이라고 할 수 있다.

    작업 단계


    프로젝트 작성


    우선 적당한 폴더에서 다음 명령을 실행하여 프로젝트를 만듭니다.아주 평범하다cargo.이름은 나한테 맡겨.
    cargo new image-viewer
    

    글꼴 파일 정렬


    기본적으로 Iced에서는 문자만 표시할 수 있으므로 일본어를 표시하기 위해 글꼴 파일을 다운로드하고 구성합니다.
    글꼴은 뭐든지 좋으니 일단 자주 쓰는 노트산스의 레귤러 방법을 적어보자.
    https://fonts.google.com/specimen/Noto+Sans+JP
    여기 있는 "Reglar400"의 "Select this style"을 선택하고 "Download all"에서 다운로드하여 zip 파일을 동결해제합니다.
    이번 프로젝트 디렉터리Cargo.toml가 있는 디렉터리에'fonts'폴더를 만들어 해동 결과.otf 파일을 설정합니다.그렇게 말하지만 어디에나 배치할 수 있고 뒤에 코드가 나오는 읽기 경로가 그만큼 바뀌면 문제없다.

    Cargo.toml 편집


    Iced 관계식은 dependencies에 기재됩니다.
    Cargo.toml
    [dependencies]
    iced = {version = "0.3", features = ["image"]}
    iced_native = "0.4"
    
    이미지 표시에 Image 애플릿을 사용하기 위해 features를 iced로 지정합니다.이게 없으면 컴파일 오류가 발생할 수 있습니다.

    main.rs의 편집


    주요 소스 코드는 다음과 같다.참고로 가볍게 댓글을 달았다.
    main.rs
    use iced::{
        executor, Align, Application, Clipboard, Column, Command, Container, Element, Image, Length,
        Settings, Subscription, Text,
    };
    use std::path::PathBuf;
    
    pub fn main() -> iced::Result {
        // フォントを指定しつつ実行する。
        Events::run(Settings {
            default_font: Some(include_bytes!("../fonts/NotoSansCJKjp-Regular.otf")),
            ..Settings::default()
        })
    }
    
    // メインとなる構造体。アプリで保持する状態を変数にする。
    #[derive(Debug, Default)]
    struct Events {
        path: PathBuf,
    }
    
    // 何らかの変更があったときに飛ぶメッセージ。今回はイベント発生のみ。
    #[derive(Debug, Clone)]
    enum Message {
        EventOccurred(iced_native::Event),
    }
    
    impl Application for Events {
        type Executor = executor::Default;
        type Message = Message;
        type Flags = ();
    
        fn new(_flags: ()) -> (Events, Command<Message>) {
            (Events::default(), Command::none())
        }
    
        // ウィンドウのタイトル。状態に合わせた動的な生成も可。
        fn title(&self) -> String {
            String::from("Image Viewer")
        }
    
        // 何らかの変更があったときに呼び出される。
        // 発生した事柄はenum(今回の場合はMessage)として伝えられる。
        // Icedのバージョン0.3から引数にClipboardが増えたが、使わないので無視。
        fn update(&mut self, message: Message, _clipboard: &mut Clipboard) -> Command<Message> {
            // ファイルがドロップされたときに、アプリの状態を変更する。
            // Eventのenumの中に、イベントの内容(別のEventのenum)とか、
            // 今回のFileDroppedではファイルパスが含まれたりする。
            match message {
                Message::EventOccurred(event) => {
                    if let iced_native::event::Event::Window(we) = event {
                        if let iced_native::window::Event::FileDropped(path) = we {
                            self.path = path;
                        }
                    }
                }
            };
    
            Command::none()
        }
    
        // イベントが発生したときに呼び出される。マウス操作、ウィンドウ関係、キーボード操作等。
        // 何らかのSubscriptionを返すことで、update()が実行される。
        fn subscription(&self) -> Subscription<Message> {
            iced_native::subscription::events().map(Message::EventOccurred)
        }
    
        // 表示されるGUIを生成する。
        fn view(&mut self) -> Element<Message> {
            // ファイルパス表示部
            let mut p = self.path.to_str().unwrap_or("").to_string();
            if p.is_empty() {
                p = String::from("画像ファイルをウィンドウにドロップしてね。");
            }
            let path = Container::new(Text::new(p).size(20)).padding(4);
    
            // 画像表示部
            let image = Container::new(
                Image::new(self.path.clone())
                    .width(Length::Fill)
                    .height(Length::Fill),
            )
            .height(Length::Fill)
            .width(Length::Fill)
            .align_x(Align::Center)
            .align_y(Align::Center);
    
            let content = Column::new()
                .width(Length::Fill)
                .align_items(Align::Start)
                .push(path)
                .push(image);
    
            Container::new(content)
                .width(Length::Fill)
                .height(Length::Fill)
                .into()
        }
    }
    

    실행


    프로젝트 디렉터리에서 다음 명령을 통해 프로그램을 실행합니다.
    cargo run --release
    
    --release의 추가 옵션을 실행하는 것은 동작 속도의 관계이다.흔한 녀석.
    일반적인 디버깅의 경우 Iced 동작이 느려서 이미지를 표시하는 데 시간이 오래 걸립니다.특히 큰 이미지 파일을 표시할 때 현저하다.
    빌딩을 발행하는 데 3배 정도의 시간이 걸리기 때문에 개발 과정에서 디버깅을 할 수 있을 것 같다.

    코드 보충


    기본 동작 등은 상기 소스 코드에 기재되어 있기 때문에 보충한다.

    Application


    Iced에서 기본 응용으로 제작된 것SandboxApplication 중 하나를 선택할 수 있다.ApplicationSandbox와 비교하면 제작이 조금 복잡합니다.
    이번에Application.서류의 하단과 같은 무원 사건을 받아들이기 위해Application 진행해야 하기 때문이다.또 타이머 등 비동기 운동을 하는 경우도 마찬가지다.Command 많이 할 수 있을 것 같은데 아직 이해가 안 가요.

    복수의 이벤트


    Iced가 여러 개enum Event나 있어서 귀찮아요.
    이번에는 기본적인 이벤트iced_native::event::Event와 콘텐츠 창용iced_native::window::Event을 사용했고, 키보드용, 마우스용, 터치용도 있었다.
    위의 코드처럼 완전히 지정하는 것은 정공법이라고 생각하지만, 스스로 별명을 짓는 방법도 있으니 취향에 따라 하세요.

    다른 하고 싶은 일


    표시할 이미지 처리 및 부품 크기

    Image 이미지는 애플릿을 통해 표시되지만 자동으로 확대/축소되어 표시되므로 매우 쉽습니다.
    하지만 반대로 신경 쓰는 일을 하려면 스스로 그림을 가공하는 것이 필요하다.예를 들어 그림의 일부분만 표시하거나 축소 알고리즘을 바꾸는 등이다.그리고 이번 프로그램은 파일의 호버에 테두리를 표시하고 싶어요.
    그림을 처리하는 크레인을 사용하면 무엇이든 할 수 있을 것 같지만 화면에 보이는 Image 애플릿의 사이즈(=최종 디스플레이 사이즈)를 구할 수 없을 것 같아 잘 가공되지 않을 것 같다.
    아니면 이번 코드Image가 양복에 호응하는 가변 사이즈라는 게 그런 것 같아요.고정 사이즈면 길을 잃지 않아요.아마 상태에 따라 가변 사이즈Image와 스크롤 구역에 넣은 고정 사이즈Image로 전환해야 할 것 같습니다.

    파일 지정 대화 상자


    파일을 여는 방법으로도 파일 대화상자가 있지만, Rust로 이 미묘한 인식을 실현한다.특히 아이스드와 같은 퓨어 러스트의 크로스플랫폼 환경을 고려하면 어떻게 하면 좋을지 모르겠다.
    이번에는 파일을 드래그해서 그림을 표시하는 방법도 회피 전략이다.아이스드만 있으면 끝나니까.

    최후


    Rust의 GUI가 아직 미숙하기 때문에 규범화된 제품 수준의 물건을 만들려는 것은 가시밭길이다.장래에 시간이 해결될 것이다.
    하지만 GUI처럼 거대한 크레인이 불가피한 경우에도 재단 주도는 가능하다.문화·사상적으로 하지 않지만.
    그나저나 GUI 수준이라면 Rust가 너무 과장된 것 같아.메모리 관리와 유형 촘촘성 등 장점도 크지만, 애플리케이션처럼 쉽게 쓰고 싶은 유형이라면 Rust가 적합하다고 말하기 어렵다.
    뭐, Rust는 구가 시스템의 프로그래밍 언어인데, 이것은 당연한 것이다.재능을 헤아려 채용하다.

    좋은 웹페이지 즐겨찾기