13 个不稳定版本 (6 个重大更改)
使用旧的 Rust 2015
0.16.0 | 2019年4月14日 |
---|---|
0.15.3 | 2019年3月25日 |
0.15.2 | 2019年1月15日 |
0.15.0 | 2018年9月12日 |
0.11.0 | 2017年11月26日 |
#8 in #relm
每月下载次数42
用于 titanium-web-extension
9KB
176 行
Relm
异步、基于 GTK+ 的 GUI 库,受 Elm 启发,用 Rust 编写。
这个库处于测试阶段:它尚未经过彻底测试,API 可能随时更改。
需求
由于 relm 基于 GTK+,您需要在您的系统上安装此库才能使用它。
有关如何安装 GTK+ 的信息,请参阅 此页面。
用法
首先,将以下内容添加到您的 Cargo.toml
[source,toml]
gtk = "^0.16.0"
relm = "^0.24.0"
relm-derive = "^0.24.0"
然后,将以下内容添加到您的 crate
[source,rust]
use relm::{connect, Relm, Update, Widget};
use gtk::prelude::*;
use gtk::{Window, Inhibit, WindowType};
use relm_derive::Msg;
然后,创建您的模型
[source,rust]
struct Model {
// …
}
模型包含与 Widget
相关的数据。它可以通过 Widget::update
函数进行更新。
创建您的消息 enum
[source,rust]
#[derive(Msg)]
enum Msg {
// …
Quit,
}
消息被发送到 Widget::update
以指示发生了事件。在接收到事件时,模型可以更新。
创建一个表示包含 GTK+ 小部件(在这种情况下,应用程序的主窗口)和模型的 struct
[source,rust]
struct Win {
// …
model: Model,
window: Window,
}
为了使此 struct
成为库可以显示的 relm Widget
,实现 Update
和 Widget
特性
[source,rust]
impl Update for Win {
// Specify the model used for this widget.
type Model = Model;
// Specify the model parameter used to init the model.
type ModelParam = ();
// Specify the type of the messages sent to the update function.
type Msg = Msg;
// Return the initial model.
fn model(_: &Relm<Self>, _: ()) -> Model {
Model {
}
}
// The model may be updated when a message is received.
// Widgets may also be updated in this function.
fn update(&mut self, event: Msg) {
match event {
Msg::Quit => gtk::main_quit(),
}
}
}
impl Widget for Win {
// Specify the type of the root widget.
type Root = Window;
// Return the root widget.
fn root(&self) -> Self::Root {
self.window.clone()
}
// Create the widgets.
fn view(relm: &Relm<Self>, model: Self::Model) -> Self {
// GTK+ widgets are used normally within a `Widget`.
let window = Window::new(WindowType::Toplevel);
// Connect the signal `delete_event` to send the `Quit` message.
connect!(relm, window, connect_delete_event(_, _), return (Some(Msg::Quit), Inhibit(false)));
// There is also a `connect!()` macro for GTK+ events that do not need a
// value to be returned in the callback.
window.show_all();
Win {
model,
window,
}
}
}
最后,通过调用 Win::run()
来显示此 Widget
[source,rust]
fn main() {
Win::run(()).unwrap();
}
#[widget]
属性
提供了一个 #[widget]
属性,以简化小部件的创建。
此属性执行以下操作:
- 提供一个
view!
宏,用于使用声明性语法创建小部件。 - 自动创建
fn root()
、type Msg
、type Model
、type ModelParam
和type Root
项。 - 在将属性分配给模型时,自动在
update()
函数中插入对Widget::set_property()
的调用。 - 自动创建
Widget
struct
。 - 可以同时实现
Update
和Widget
特性。
要使用此属性,请添加以下代码
[source,rust]
use relm_derive::widget;
以下是一个使用此属性的示例
[source,rust]
#[derive(Msg)]
pub enum Msg {
Decrement,
Increment,
Quit,
}
pub struct Model {
counter: u32,
}
#[widget]
impl Widget for Win {
fn model() -> Model {
Model {
counter: 0,
}
}
fn update(&mut self, event: Msg) {
match event {
// A call to self.label1.set_text() is automatically inserted by the
// attribute every time the model.counter attribute is updated.
Msg::Decrement => self.model.counter -= 1,
Msg::Increment => self.model.counter += 1,
Msg::Quit => gtk::main_quit(),
}
}
view! {
gtk::Window {
gtk::Box {
orientation: Vertical,
gtk::Button {
// By default, an event with one paramater is assumed.
clicked => Msg::Increment,
// Hence, the previous line is equivalent to:
// clicked(_) => Increment,
label: "+",
},
gtk::Label {
// Bind the text property of this Label to the counter attribute
// of the model.
// Every time the counter attribute is updated, the text property
// will be updated too.
text: &self.model.counter.to_string(),
},
gtk::Button {
clicked => Msg::Decrement,
label: "-",
},
},
// Use a tuple when you want to both send a message and return a value to
// the GTK+ callback.
delete_event(_, _) => (Msg::Quit, Inhibit(false)),
}
}
}
注意:由于属性的原因,现在自动创建了 struct Win
,以及函数 root()
和相关类型 Model
、ModelParam
、Msg
和 Container
。如果需要,您仍然可以提供方法和相关类型,但不能创建 struct
。
警告:由于 #[widget]
使生成的 struct
公开,因此相应的模型和消息类型也必须是公开的。
[警告]
当使用此属性时,由于代码生成简单,您的程序可能会变慢。例如,以下代码 [source,rust]
fn update(&mut self, event: Msg) {
for _ in 0..100 {
self.model.counter += 1;
}
}
将生成此函数:[source,rust]
fn update(&mut self, event: Msg) {
for _ in 0..100 {
self.model.counter += 1;
self.label1.set_text(&self.model.counter.to_string());
}
}
[警告]
此外,目前只有在将属性分配给模型时才插入对 set_property()
的调用。例如,以下代码 [source,rust]
fn update(&mut self, event: Msg) {
self.model.text.push_str("Text");
}
将无法按预期工作。
如果需要,请使用以下变体。 [source,rust]
fn update(&mut self, event: Msg) {
self.model.text += "Text";
}
有关如何使用 relm 的更多信息,您可以查看 示例。
捐赠
如果您喜欢这个项目并希望实现新功能,请通过 Patreon 支持我。
使用 relm
的项目
- Yellow Pitaya:红pitaya 硬件示波器的桌面界面。
- Game of Life:康威生命游戏模拟器
- Country Parser:解析 Google 位置历史记录并显示访问过的国家的时间线
- Chessground:一个实验性的棋盘小部件
- Effitask:基于todo.txt格式的图形化任务管理器
- KS Curve Tracer:AD2曲线追踪器的配套应用程序
- Cigale:准备你在工作中完成的任务时间表的工具
- Projectpad:作为软件开发人员或系统管理员,管理机密凭证和服务器信息。
- TimezoneRS:一个GUI应用程序,可以直观地查看不同时区的时间
- Tubefeeder / Pipeline:在一个地方观看YouTube、LBRY和PeerTube视频。
- Hotwire:以简单的方式研究一些流行协议的网络流量
- gue:控制飞利浦Hue灯的GUI
- MyCitadel钱包:MyCitadel加密货币钱包应用程序
如果您想将您的项目添加到这个列表中,请创建一个pull请求。
依赖关系
约2MB
约49K SLoC