Rust에서 GUI ~azul편~

12572 단어 GUIazulRust
전체 코드는 github ogata-k/GUI_cmp/example_azul를 참조하십시오.

azul



azul(version 0.1.0 )는 Rust 1.28 이상을 지원하므로 rustc -vV에서 Rust 컴파일러 버전이 지원되는지 확인하십시오.

어떤 크레이트가



azul은 Mozilla의 브라우저 렌더링 엔진을 기반으로 Rust로 작성된 IMGUI 지향 (즉, "Immediate Mode GUI"라는 패러다임을 채택한) GUI 프레임 워크입니다. IMGUI 지향을 간단히 말하면 "요청되었을 때 요구된 것만 처리한다"는 느낌(잘못되었을지도)이 됩니다.
azul은 HTML과 같은 DOM 스타일을 사용하여 widget 구조를 나타내며 (azul 용) CSS로 장식을 처리하는 형태를 취하고 있습니다.
자세한 내용은 azul Tutorial(영어) 또는 공식 사이트을 참조하십시오.

코드



카운트 업 프로그램을 작성합니다.

style.css
#label{
  color: black;
  font-size: 160px;
  background-color: yellow;
}

#button{
  font-size: 10px;
  margin: 5px;
  background-color: blue;
}

* {
   font-size: 27px;
}

main.rs
extern crate azul;

use azul::{prelude::*, widgets::{label::Label, button::Button}};
use azul::window_state::WindowSize;
// レイアウトに依存するデータモデルの定義
struct DataModel {
  count_num: usize,
}

// レイアウトの実装
impl Layout for DataModel {
  // render関数
  fn layout(&self, info: LayoutInfo<Self>) -> Dom<Self> {
    // domでビルドするビルダーパターンのイメージでwidgetの作成
    let label = Label::new(format!("{}", self.count_num)).dom().with_id("label");
    // domにしてから関数を設定
    let button = Button::with_label("カウントアップ +1").dom().with_id("button")
      .with_callback(On::MouseUp, Callback(update_counter));

    // HTMLのような感じでレイアウトの部品となるDomを返す
    Dom::new(NodeType::Div)
      .with_child(label)
      .with_child(button)
  }
}


// appの情報とイベントの情報を受け取って計算したあとにスクリーンに状態を伝搬する関数
fn update_counter(app_state: &mut AppState<DataModel>, _event: &mut CallbackInfo<DataModel>) -> UpdateScreen {
  app_state.data.modify(|state| state.count_num += 1);
  // 再描画の必要が無いときはRedrawの代わりにDontRedrawを使う
  Redraw
}

fn main() {
  // GUIのルートの作成
  // 引数はレイアウトを決定する初期条件とログやエラー処理に関するデータ構造
  let app = App::new(DataModel {count_num: 0}, AppConfig::default());

  // Windowの設定
  let mut window_options = WindowCreateOptions::default();
  window_options.state.title = "カウントアップ".to_string();
  let mut window_size = WindowSize::default();
  window_size.dimensions = LogicalSize::new(400.0, 300.0);  // width * height
  window_options.state.size = window_size;

  // CSSの設定
  macro_rules! CSS_PATH { () => (concat!(env!("CARGO_MANIFEST_DIR"), "/src/style.css")) }
  let css = css::override_native(include_str!(CSS_PATH!())).expect(&format!("failed: override CSS by {}", CSS_PATH!()));

  app.run(Window::new(window_options, css).expect("failed: make window")).expect("failed: start running application");
}



코드 설명



먼저 이번에 조작할 데이터의 대상을 구조체로 준비합니다.
예를 들면 다음과 같습니다.
// レイアウトに依存するデータモデルの定義
struct DataModel {
  count_num: usize,
}

이 데이터 모델을 타겟으로 레이아웃을 준비(구현)하여 데이터를 다루는 DOM을 작성할 수 있도록 해 둡니다. Button DOM 메서드의 마우스 상태와 콜백 함수를 받기 with_callback에서 볼 수 있듯이 콜백 함수도 쉽게 설정할 수 있습니다. 콜백 함수 update_counter는 발생한 이벤트를 기반으로 호출자가 보유한 데이터 모델을 다시 작성하는 형태의 함수입니다. 반환값은 재묘화를 요구하는 Redraw 와 재묘화를 요구하지 않는 DontRedraw 의 2치로 이루어진 열거형 UpdateScreen 입니다. 이 UpdateScreen 값을 보고 다시 그리기의 필요성을 결정하면 azul은 불필요한 다시 그리기를 줄일 수 있습니다.
다음은 main 함수입니다.
기본 구조는 다른 흔한 GUI 라이브러리와 동일한 쓰기 방법입니다.
이번 app 의 초기 조건을 모두 쓰고 있습니다. 다른 파일에서 읽은 값으로 초기화하는 형태로 초기 조건을 주어도 좋다고 생각합니다.
방금 초기화된 app에는 window의 설정과 장식인 css가 설정되어 있지 않으므로 각각 설정해 줍니다.
마지막으로 app를 실행하여 종료합니다.

소감



솔직히 아직 개발 도중에 의존하는 크레이트가 많은 탓인지 컴파일은 무겁습니다. 또한 window 크기와 같은 설정은 Default::default 함수가 있지만 중첩이 조금 깊고 조금 번거롭습니다. set〇〇 같은 메서드를 원하는 곳입니다. (찾지 못했을 뿐입니다.)
다만 레이아웃이나 장식에 관한 정보가 CSS로 대체로 기술할 수 있는 것은 강하다고 생각합니다. IMGUI 지향의 레이아웃은 일반적으로 복잡하게 하기 어렵다고 합니다만, 이 CSS에 의한 기술이 다소 해결해 주는 것처럼 느낍니다.
다만 CSS에 관해서는 잘 적용되지 않는 경우도 많아 아직 미성숙하다고 생각됩니다.

요약



아직도 미숙한 점이 많고 문서도 거의 없기 때문에 실용으로는 멀리 느낍니다. 그러나 IMGUI 지향 CSS로 레이아웃이 향상된 DOM형 GUI 라이브러리는 사용하기 쉽습니다. 그래서 version 1.0.0을 넘은 후의 안정 버전을 기대하고 싶은 곳입니다.

좋은 웹페이지 즐겨찾기