前言
- 在notion-rss发布后,有用户评论不太会使用命令行工具,所以想写给命令行写一个图形化界面,经过调研,最后选择了tauri。下面来记录一下使用tauri开发图形化界面的过程和坑。
Rust的GUI框架对比
- state-of-rust-gui-libraries这篇文章对比了rust常见的gui库,主要在是否跨平台开发,是否能已经成熟能用在生产环境。
- 经过比较感觉fltk-rs和tauri还行的,gtk的整个架构太大了,就编译工具链就劝退了,然后下面很多都是基于gtk封装了一层,让用户使用起来不再这么麻烦,还有要学习多一种标记语言,学习成本太高了。
|
Production ready |
Compatibility |
gtk-rs |
Yes |
Cross-platform |
fltk-rs |
Yes |
Cross-platform |
iced |
No |
Cross-platform and web |
relm |
No |
Cross-platform |
Azul |
Yes |
Cross-platform |
egui |
Older Releases |
Cross-platform |
Tauri |
Yes |
Desktop and web |
Slint |
Yes |
Web |
Druid |
Yes |
Desktop and web |
- 最后因为fltk-rs不够现代化,选了Tauri。主要看生态了文档,Tauri只需要用HTML写完前端,真正的所见及所得,本来也会Vue,几个UI库,所以不用再学什么东西,直接可以上手。
- 和electron的对比,总之吊打electron。
环境搭建
➜ cargo install create-tauri-app
➜ cargo install tauri-cli
初始化项目
- 如果已经有项目了,可以创建完再拷贝进文件里,改一下文件名,rust的源文件在
src-tauri
,前端项目源文件在src
,两个都可以分别开发。
➜ IdeaProjects cargo create-tauri-app
✔ Project name · tauri-app
✔ Choose your package manager · cargo
✔ Choose your UI template · vanilla
Please follow <https://tauri.app/v1/guides/getting-started/prerequisites> to install the needed prerequisites, if you haven't already.
You also need to install tauri-cli (cargo install tauri-cli)
Done, Now run:
cd tauri-app
cargo tauri dev
➜ IdeaProjects
- 这样创建的项目前端是纯HTML,JS的,开发大项目不太适合,建议先开始写前端,再进去前端目录用
cargo tauri init
初始taruri项目。
tauri.conf.json
- 初始化完成后会在src-tauri文件夹生成配置文件tauri.conf.json,可以开启和关闭一些危险模块,设置分发参数。
自定义icon图标
➜ notion-rss git:(main) ✗ cargo tauri icon src-tauri/icons/index.ico
Window系统隐藏命令行控制台
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
Rust与前端互相调用
前端调用Rust
#[tauri::command]
pub async fn init_user() -> Option<notion_sdk::user::User> {
if let Ok(Object::User { user }) = NOTION_FEED.notion.users_me().await {
return Some(user);
}
None
}
invoke_handler
注册调用方法generate_handler
let builder = tauri::Builder::default()
.system_tray(tauri::SystemTray::new().with_menu(MyTray::tray_menu()))
.setup(|app| {
resolve_setup(app);
Ok(())
})
.on_system_tray_event(MyTray::on_system_tray_event)
.invoke_handler(tauri::generate_handler![
notion_rss::ui::save_config,
notion_rss::ui::init_config,
notion_rss::ui::init_user,
notion_rss::ui::update_once,
notion_rss::ui::run_api_server
]);
- 在前端就可以使用
invoke
调用init_user
// 初始化用户信息
async init_user() {
if (
this.config.notion_token &&
this.config.archive_id &&
this.config.source_id
) {
invoke("init_user")
.then((response) => {
this.user = response;
})
.catch((error) => {
this.snackbar = { text: error, show: true, color: "error" };
});
}
},
Rust调用前端
- 文档,在Rust调用前端需要用到事件,首先要在前端页面创建一个监听事件,下面只是把从Rust发送过来的Paylad通过snackbar提示出来,防止多次监听这段代码要在
created
方法中调用。PROGRESS
为你监听的事件。
// 监听事件
async event_listen() {
await appWindow.listen("PROGRESS", ({ event, payload }) => {
console.log(event, payload);
this.snackbar = {
text: payload.toString(),
show: true,
color: "success",
};
this.update_loading = false;
});
},
- 在Rust中接收一个
tauri::Window
类型的参数
#[tauri::command]
pub async fn update_once(window: tauri::Window) {
update(Some(window.clone())).await;
}
- 要推送信息时调用window的
emit
方法就可以将Payload推送到PROGRESS
监听事件中。
window.emit("PROGRESS", err.to_string()).unwrap_or_default();
发布版本
- 官方在github中有action,发布版本只需要创建CI文件改改就可以了,非常方便,缺点是没办法静态编译,没办法自定义文件名。所以Mac系统的M1架构暂时没发布。
参考