Rust图形界面库初探
最近打算用rust把以前写的代码重构一下,涉及到GUI界面怎么选择的问题。rust正式发布不过十年光景,在GUI开发这方面还不如老牌的C/C++,有诸如wxWidgets、qt、gtk+等众多知名又久经考验的GUI界面库。本文选取几款rust的GUI库,简单实现一个边界层计算器,做个横向对比。
1. slint
slint 近期的宣传不可谓不卖力,号称要打造成下一代gui工具包,看来野心不小。slint通过自定义的声明式语言定义ui界面,在vscode下编程可以通过插件预览,也可以通过官方的slintpad 网站预览。
cargo配置文件如下,slint-build用于将.slint界面文件翻译成.rs文件。
[package]
name = "sLayers-rs"
version = "0.1.0"
edition = "2024"
[dependencies]
slint = "1.8.0"
[build-dependencies]
slint-build = "1.8.0"
[profile.release]
strip = true
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
ui界面文件dialog.slint。slint可以把需要调用的参数定义到ui界面中,并自动隐式生成set_和get_方法用于在rs文件中设置这些参数的值。同样的,界面中定义的回调函数也会自动隐式生成on_方法,用于在rs文件中调用。需要注意的是,在rs中更新了ui界面中的参数,关联的控件并不会自动更新显示,需要手动更新控件显示。
import { Button, LineEdit, SpinBox, CheckBox, GridBox, VerticalBox } from "std-widgets.slint";
export component Dialog inherits Window {
title: "Layers";
in-out property <string> tt: "3.0";
in-out property <int> nl: 5;
in-out property <string> ft: "0.3";
in-out property <string> gr: "1.5";
callback calculate_first_thickness();
callback calculate_num_layers();
callback calculate_growth_rate();
callback calculate_total_thickness();
callback calculate_value();
VerticalBox {
Text {
text: "Calculate fluid boundary layer parameters.\nCalculate the selected parameters based on the others.";
}
GridBox {
Row {
b_t := CheckBox {
text: "Total thickness (mm)";
checked: true;
enabled: !self.checked;
toggled() => {
if self.checked {
b_n.checked = false;
b_f.checked = false;
b_g.checked = false;
}
}
}
e_t := LineEdit {
text: root.tt;
input-type: decimal;
read-only: b_t.checked;
}
}
Row {
b_n := CheckBox {
text: "Number of layers";
checked: false;
enabled: !self.checked;
toggled() => {
if self.checked {
b_t.checked = false;
b_f.checked = false;
b_g.checked = false;
}
}
}
e_n := SpinBox {
value: root.nl;
minimum: 1;
}
}
Row {
b_f := CheckBox {
text: "First thickness (mm)";
checked: false;
enabled: !self.checked;
toggled() => {
if self.checked {
b_n.checked = false;
b_t.checked = false;
b_g.checked = false;
}
}
}
e_f := LineEdit {
text: root.ft;
input-type: decimal;
read-only: b_f.checked;
}
}
Row {
b_g := CheckBox {
text: "Growth rate";
checked: false;
enabled: !self.checked;
toggled() => {
if self.checked {
b_n.checked = false;
b_f.checked = false;
b_t.checked = false;
}
}
}
e_g := LineEdit {
text: root.gr;
input-type: decimal;
read-only: b_g.checked;
}
}
}
Button {
text: "Calculate";
clicked => {
root.tt = e_t.text;
root.nl = e_n.value;
root.ft = e_f.text;
root.gr = e_g.text;
if b_t.checked {
root.calculate_total_thickness();
} else if b_n.checked {
root.calculate_num_layers();
} else if b_f.checked {
root.calculate_first_thickness();
} else if b_g.checked {
root.calculate_growth_rate();
}
e_t.text = root.tt;
e_g.text = root.gr;
e_f.text = root.ft;
e_n.value = root.nl;
}
}
}
}
build.rs构建脚本调用slint-build将.slint文件翻译成.rs文件。