Rust GUI 编程漫谈:超越 Web 与原生 GUI

2021-05-11 15:18:50 浏览数 (1)

自打我有了一个写 Uncode IDE 的小目标之后,我开始寻找一些适用于 Rust 语言的 GUI 框架。对于未来而言,基于 Rust 语言写 GUI 提供了大量的优点。

  • 浏览器环境。在进程分离的架构下,意味着我们可以用 Rust 写 GUI 后端,用于提供语言服务等;Rust 写前端则可以编译为 WebAssembly,以更好的性能在浏览器上运行。
  • 本地运行。没啥说的,怎么地也不如再有的 GUI 框架做得好。
  • 移动设备上运行。就是想想,说不定还能实现。

于是,在我这一个月的努力之下,我尝试了三个不同风格的 Rust GUI 框架:终于总算是勉强能跑起来了。顺便一提,这三个框架都不是稳定版本,功能都不够完善。

唯一值得称道的一点是,我写这篇文章用的工具用的是其中的 Druid 框架写的 Print 编辑器吧。它可以稳定的运行着,虽然功能还不够完善,但是勉强可以用起来。

而且,从输入的效果来看,输入的响应速度还是相当不错的 —— 毕竟在没有各种智能 智障提醒的情况下,它不会有多慢。

混合框架 Tauri

为了方便于开发,我开始我假设 Uncode 是运行在浏览器环境的,所以呢,我就找了 Electron 的替代器 Tauri。

Tauri 走的是古老的混合应用框架 Cordova 的思路,通过调用系统默认的 WebView 来作为环境。想想,还是很美好的,所以我尝试了使用 Tauri 运行了第一个 hello, world。然后试着,加了几个功能,也是勉强能接受的,直到我需要一个多窗口的功能,发现没有。

于是,我去 GitHub 上了解了一下情况,看了一眼 Todo:

  • Frameless Mode (coming soon)
  • Transparent Mode (coming soon)
  • Multiwindow Mode (coming soon)

看了一眼时间,没错今年是 2021 了,这些个 Todo 这么多,我还怎么继续啊。

小结,其实呢,如果你用过 Cordova 的话,那你就知道 Cordova 在跨平台上的诸多问题。不过,写写小工具还是相关不错的,hello,world 只需要 600 KB,体积少了 100M 还是很香的。

跨 Web 与原生框架 Iced

接着,我开始寻找了第二个 GUI 框架,我看到了一个更美好的框架 Iced:用 Iced 写的应用,除了可以在桌面上运行,还可以编译为 Web 应用在浏览器上跑。有没有很香??

拿起 Iced 就开发干了:

  • Flexd 布局 1 分,
  • 独立的 Style 编写 1 分
  • ……

如下是使用 Iced 编写的 Style,支持一定程度的自定义:

代码语言:javascript复制
mod style {
...

impl container::StyleSheet for ProjectToolWindow {
  fn style(&self) -> container::Style {
    container::Style {
      backg round: Some(Background::Color([1.0, 1.0, 1.0].into())),
      text_color: Some(Color::BLACK),
      ..container::Style::default()
    }
   }
 }
}

那,我们来写个编辑器吧。咦,没有多行 text input。我思考了一下一个编辑器的工作量,我决定放弃这个框架。

总结:API 非常友好,至少我是觉得不错滴,但是 widget 不全。

桌面级 Druid

我要醒醒醒醒,原生 GUI 开发和 Web UI 开发不一样,大部分组件库没那么全的。嗯,看来这样一来,我的目标就很清晰了:多窗口 多行文本。一波努力之下,我找到了 Druid。然后看了看作者的头像,似乎有点眼熟,点进去一眼,原来就是那个写 Xi Editor 的作者了。

  • 编辑器支持功能 GET。同时还有 xi-win 作为参考版本,widget 里还提供了多行文本的支持,也就是我现在在写本文的这个工具,用的就是多行文本。虽然,后期得自定义,但是至少得是 it works。
  • 内置多语言支持。
  • 官方提供了主题的 Demo。
  • 官方有一个参考应用:字体编辑器。

排版方式上,同样是可以用 Flex,如下:

代码语言:javascript复制
fn make_ui() -> impl Widget<AppState> {
Flex::column()
.with_child(navigation_bar())
.with_flex_child(center(), 1.0)
.with_child(bottom_tool_window())
.with_child(status_bar())
.background(crate::theme::BACKGROUND_COLOR)
}

比较有意思的是,这个框架内置了大量的 GUI 范式,你得按它的模式来编写。

总结:基本可用的 Rust GUI 库,文档还有待完善。

0 人点赞