3 个版本 (破坏性更新)
0.3.0 | 2024 年 2 月 11 日 |
---|---|
0.2.0 | 2024 年 2 月 8 日 |
0.1.0 | 2024 年 1 月 28 日 |
#461 in GUI
170KB
3.5K SLoC
Finestra
Finestra 是一个简单实用的 Rust 桌面 UI 框架。它通过集成到各平台的本地 UI 后端,保持了每个平台的原生外观和感觉。使用 Finestra,您可以编写同时针对 Windows 和 macOS 的应用程序。
安装
Finestra 提供了一个 crate,其中包含您开始开发桌面应用程序所需的所有工具
[dependencies]
finestra = "0.1.0"
示例
以下示例通过提供一个按钮来演示 Finestra 的基本用法,每次点击按钮时,按钮的文本都会更新。
use finestra::*;
struct MyApplication;
impl AppDelegate<AppState> for Application {
fn make_content_view(&mut self, state: &mut AppState, _: Window) -> impl finestra::View<Self, AppState> {
state.label.set("Count: 0");
Button::new(&state.label)
.with_on_click(|state: &mut AppState, window: Window| {
state.count += 1;
state.label.set(format!("Count: {}", state.count));
if state.count % 10 == 0 {
window.create_dialog(format!("You clicked {} times!", state.count))
.show();
}
})
}
}
#[derive(Debug, Default)]
struct AppState {
count: usize,
label: TextValue,
}
fn main() {
App::with_state(MyApplication, AppState::default())
.run();
}
用法
该 crate 提供了一个入口点,即 App
结构体。
App::new(MyApplication::default()).run()
为了响应常见事件(如 启动)以及 configure
和 populate
窗口,您必须提供 AppDelegate
实现。
struct MyApplication;
impl AppDelegate for MyApplication {
fn did_launch(&mut self, _: &mut ()) {
println!("Taking Off 🚀");
}
fn configure_main_window(&mut self, _: &mut ()) -> WindowConfiguration {
WindowConfiguration::new()
.with_title("Exciting Window Title 🤩")
}
fn will_show_window(&mut self, _: Window, _: &mut ()) {
println!("About to show the window, be prepared! 👀");
}
fn make_content_view(&mut self, _: &mut (), _: Window) -> impl View<Self> {
Label::new("Welcome to Finestra!")
}
}
状态
一个强大的应用程序开发工具是 State<T>
对象,它是一个共享和订阅对象,您可以使用它一次性编写,然后在任何地方更新。它类似于 WPF 的 绑定 和 SwiftUI 的 绑定。它还与库深度融合,例如,允许您在传递 State<String>
的任何地方传递 String
/&str
。
在以下示例中,用户可以通过更改 TextField
的内容来修改窗口的标题。
struct Application;
impl AppDelegate<AppState> for Application {
fn configure_main_window(&mut self, state: &mut AppState) -> WindowConfiguration {
state.title.set("My Application");
WindowConfiguration::new()
.with_title(state.title.clone())
}
fn make_content_view(&mut self, state: &mut AppState, _: Window) -> impl finestra::View<Self, AppState> {
Stack::horizontal()
.with(Label::new("Choose a title:"))
.with(TextField::new(state.title.clone()))
}
}
#[derive(Debug, Default)]
struct AppState {
title: TextValue,
}
fn main() {
App::with_state(Application, AppState::default())
.run();
}
堆叠
要将多个项目放置在同一行或列中,请使用 Stack
视图。这可以是水平(行状)或垂直(列状)。
fn make_content_view(&mut self, _: &mut (), _: Window) -> impl finestra::View<Self, ()> {
Stack::horizontal()
.with(Label::new("Hello, world!"))
.with(Button::new("Click Me"))
.with(Button::new("Goodbye, world!"))
}
要了解如何将这些功能结合起来创建强大的界面,请查看 计算器应用程序 示例。
对话框
当发生需要用户注意的特定事件时,您可以使用 对话框。
use rand::seq::SliceRandom;
const FRUITS: &[&str] = &[
"Apple", "Banana",
"Strawberry", "Orange",
"Kiwi", "Pear",
"Berries", "Lemon",
// "Tomato",
];
Button::new("Random Fruit")
.with_on_click(|_, window| {
window.create_dialog(FRUITS.choose(&mut rand::thread_rng()))
.title("Fruit")
.kind(DialogKind::Informational)
.show();
})
有关更多信息,请参阅 DialogBuilder 和 DialogKind
的文档。
颜色
要使用与 Finestra 支持的每个平台都一致的色彩,可以使用 SystemColor
枚举
Label::new("BlueExampleSoftware")
.with_color(Color::system(SystemColor::Blue))
这将确保您始终使用正确的颜色,并与系统应用程序保持一致。
如果您需要使用特定颜色,可以使用 Color::rgb()
和 Color::rgba()
函数
Label::new("Maroon Balloon 🎈")
.with_color(Color::rgb(155, 68, 68))
您可以使用 State<Color>
模式自然地动态更改颜色。请参阅 Disco Button 示例以了解其实现方式。
组件概述
以下组件目前由 Finestra 支持
Button
可以用来触发特定操作。ImageView
可以显示图片。Label
包含单行文本。Stack
可以水平或垂直放置项目。TextBlock
可以包含多行文本,并允许进行特定对齐。TextField
可以用来请求用户输入特定字符串。
理由
操作系统通常指定它们自己的设计语言,例如 Apple 的 人机界面指南 和 Microsoft 的 Windows 11 设计原则。这些指南提供以使用户能够体验到一致且熟悉的用户界面,并且遵守这些指南通常会被您的应用程序用户所欣赏,就像 Arc for Windows 在 X/Twitter 上受到赞扬。
_TODO: 更新博客文章_
进一步阅读
版权
版权 (C) 2024 Tristan Gerritsen
根据 Apache 许可证 2.0 版(“许可证”);除非遵守许可证,否则不得使用此文件。您可以在 https://apache.ac.cn/licenses/LICENSE-2.0 获取许可证副本。
除非适用法律要求或书面同意,否则根据许可证分发的软件按“现状”基础分发,不提供任何类型的保证或条件,无论是明示的还是默示的。有关许可证的具体语言,请参阅许可证。
除非您明确声明,否则根据Apache-2.0许可证定义,您有意提交给Serde的任何贡献,将按上述方式双授权,不附加任何其他条款或条件。
依赖项
~1-41MB
~616K SLoC