Rust에서 GUI ~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.rsextern 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
을 넘은 후의 안정 버전을 기대하고 싶은 곳입니다.
Reference
이 문제에 관하여(Rust에서 GUI ~azul편~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/ogata-k/items/fc1e21d2ba707a8b9ae7
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
#label{
color: black;
font-size: 160px;
background-color: yellow;
}
#button{
font-size: 10px;
margin: 5px;
background-color: blue;
}
* {
font-size: 27px;
}
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,
}
Reference
이 문제에 관하여(Rust에서 GUI ~azul편~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ogata-k/items/fc1e21d2ba707a8b9ae7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)