はじめに
この記事は Slint Advent Calendar 2024 12日目の記事です。
昨日は @gony さんによる Slintでモーダルダイアログを実現する という記事でした。
Slint ではまだモーダルはサポートされていないようですが、きっとそのうちされるでしょう。
Windows 限定ではありますが、自前で頑張ってる人もいました。
今日は.slint で生成したウィンドウのサイズの変更を Rust 側で検知する方法です。
ウィンドウのサイズをプロパティにする
まずは SlintPad で以下のコードを試してみましょう。
// サイズを保持する構造体を定義する
export struct Size {
width: length,
height: length,
}
export component AppWindow inherits Window {
// デフォルトの大きさを指定
preferred-width: 1280px;
preferred-height: 720px;
// ウィンドウのサイズを Size 構造体型のプロパティで保持する
out property<Size> window-size: { width: root.width, height: root.height };
label := Text {
// ウィンドウの横幅と高さを表示する
text: "\{root.window-size.width / 1px} x \{root.window-size.height / 1px}";
}
}
サイズ用の構造体 Size
を定義し、window-size
というプロパティとその値の関係を宣言しています。
ここではその値を Text
に表示しています。
String 型は文字列中に \{...}
と書くと、その中を評価して文字に置換してくれます。
なお、length
型はそのまま指定すると、
Error: Cannot convert length to string. Devide by 1px to convert to a plain number
というエラーになるため、指示どおり 1px
で割ることで数値に変換しています。
ウィンドウのプロパティが変更されたらなにかをする
つぎに、以下のコードを SlintPad で試してみます。
// サイズを保持する構造体を定義する
export struct Size {
width: length,
height: length,
}
export component AppWindow inherits Window {
// デフォルトの大きさを指定
preferred-width: 1280px;
preferred-height: 720px;
// ウィンドウのサイズを Size 構造体型のプロパティで保持する
out property<Size> window-size: { width: root.width, height: root.height };
// 上記のウィンドウのサイズに変更があったら、ラベルにウィンドウの横幅と高さを表示する
changed window-size => { label.text = "\{root.window-size.width / 1px} x \{root.window-size.height / 1px}"; }
label := Text {}
}
動作は以前と同じですが、プロパティバインディングではなく、Slint 1.8.0 で導入されたばかりの プロパティの変更ハンドラ で表示を更新しています。
コールバックで通知する
.slint 側でコールバックを定義し、ウィンドウサイズが変更されたら呼ぶようにし、Rust 側でそれを受けて処理をするようにします。
SlintPad で以下のコードを試します。
// サイズを保持する構造体を定義する
export struct Size {
width: length,
height: length,
}
export component AppWindow inherits Window {
// デフォルトの大きさを指定
preferred-width: 1280px;
preferred-height: 720px;
// ウィンドウのサイズを Size 構造体型のプロパティで保持する
out property<Size> window-size: { width: root.width, height: root.height };
// ウィンドウのサイズが変更された際のコールバック
callback window-size-changed;
// 上記のウィンドウのサイズに変更があったら、コールバックを呼ぶ
changed window-size => { window-size-changed(); }
}
今回は、.slint 上には表示されません。 main.rs 側で変更を検知し、処理を行います。
use std::error::Error;
slint::include_modules!();
fn main() -> Result<(), Box<dyn Error>> {
let ui = AppWindow::new()?;
// ウィンドウの初期サイズをプロパティから取得する
let size = ui.get_window_size();
println!("Initial Window Size: {}x{}", size.width, size.height);
let ui_handle = ui.as_weak().unwrap();
// ウィンドウサイズが変更されたら処理を行う
ui.on_window_size_changed(move || {
let size = ui_handle.get_window_size();
// 標準出力に出す
println!("Window Size Changed: {}x{}", size.width, size.height);
});
ui.run()?;
Ok(())
}
ソースコードの一式を以下で公開したので、手元で試したい人は参考にしてください。
おわりに
今回は、.slint で作成したウィンドウのサイズとその変更を、バックエンドの Rust 側で取得や検知する方法を調査しました。
明日は @hermit4 さんがによる Slint言語入門(4) 構文について(続2) です。お楽しみに!