news 2026/6/10 3:29:00

Tauri框架实战——托盘左键不显示菜单

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Tauri框架实战——托盘左键不显示菜单

背景

近期,我基于自研的个人时间管理 Web 应用「时光助手」,借助 AI 辅助开发,通过 Tauri 框架完成了 Windows 客户端的打包工作。初次体验 Tauri 便收获了不错的反馈 —— 其生成的客户端体积轻量化、运行性能优异,且与 Web 端的适配性远超预期。

不过,从 Web 应用到桌面客户端的迁移,并非简单的 “打包封装” 就能一蹴而就,目前仍有不少细节有待打磨。后续我计划从两个维度深耕:一是系统性吃透 Tauri 框架的底层逻辑与进阶用法;二是对 AI 生成的代码进行全面人工复核。毕竟 AI 生成的代码存在两个明显痛点:部分逻辑的实现原理模糊不清,可能暗藏隐患或冗余;再加上各类功能框架与组件版本差异显著、官方文档覆盖不全,AI 受限于底层机制产生的 “幻觉” 问题会被进一步放大。唯有人工逐行校验,才能让代码真正稳定可靠。

鼠标左键点击托盘图标,不弹出菜单

应用最小化到托盘后,用户如想显示主窗口或退出,通过右键托盘图标,弹出菜单实现的,当前的问题在于,用户点击鼠标左键,也会弹出菜单,需要屏蔽掉左键菜单。

依然使用 TRAE,将需求告知 ,如下:

tauri框架生成的客户端,当最小化托盘图标时,鼠标左键单击不要显示菜单,而是显示主窗口

AI 处理完后,发现代码没变化,细看发现 AI 居然跳出了原先的项目结构,新建了一个目录和文件,比较无语,如下:

/e/dev/meet/platform-web/src-tauri/src/lib.rs

明确告诉它搞错了,正确的位置是E:\dev\meet\platform-web\src-tauri\src,才对项目内应该修改的源码进行调整,看代码逻辑,监控了托盘图标的点击事件,如果判断是鼠标左键单击,则显示主窗口,代码如下:

// 修改托盘图标配置部分,完整替换以下代码:// 5. 创建系统托盘let_tray=TrayIconBuilder::new().icon(app.default_window_icon().unwrap().clone()).tooltip("时光助手").menu(&tray_menu)// 处理托盘图标点击事件 - 左键单击显示主窗口.on_tray_icon_event(|tray,event|{matchevent{TrayIconEvent::Click{button,..}=>{// 只处理左键单击ifbutton==tauri::MouseButton::Left{letapp_handle=tray.app_handle();// 获取窗口并显示ifletSome(window)=app_handle.get_webview_window("main"){let_=window.show();let_=window.set_focus();}}}TrayIconEvent::DoubleClick{..}=>{letapp_handle=tray.app_handle();// 获取窗口并显示ifletSome(window)=app_handle.get_webview_window("main"){let_=window.show();let_=window.set_focus();}}_=>{}}})// 处理菜单点击事件.on_menu_event(|tray,event|{letapp_handle=tray.app_handle();matchevent.id().as_ref(){"show_window"=>{ifletSome(window)=app_handle.get_webview_window("main"){let_=window.show();let_=window.set_focus();}}"quit_app"=>{// 退出应用app_handle.exit(0);}_=>{}}}).build(app)?;

结果,打包的时候提示编译错误……

Compilingtauri-plugin v2.5.2Compilingtauri-codegen v2.5.2InfoFilesrc-tauri\src\lib.rs changed.Rebuildingapplication...Compilingtauri-utils v2.8.1Compilingwindows v0.61.3Compilingtauri-build v2.5.3Compilingtauri-plugin v2.5.2Compilingtauri-codegen v2.5.2Compilingtauri v2.9.5Compilingtauri-macros v2.5.2Compilingtauri-plugin-os v2.3.2Compilingtauri-plugin-notification v2.3.3CompilingTimeHelperv3.4.0(E:\dev\meet\platform-web\src-tauri)Compilingwebview2-com-sys v0.38.0Compilingtao v0.34.5Compilingtauri-winrt-notification v0.7.2Compilingnotify-rust v4.11.7Compilingwebview2-com v0.38.0InfoFilesrc-tauri\tauri.conf.json changed.Rebuildingapplication...Compilingwindows v0.61.3CompilingTimeHelperv3.4.0(E:\dev\meet\platform-web\src-tauri)Compilingwebview2-com-sys v0.38.0Compilingtao v0.34.5Compilingtauri-winrt-notification v0.7.2Compilingnotify-rust v4.11.7Compilingwebview2-com v0.38.0Compilingtauri-runtime v2.9.2Compilingwry v0.53.5Compilingtauri-runtime-wry v2.9.3Compilingtauri v2.9.5Compilingtauri-plugin-single-instance v2.3.6Compilingtauri-plugin-notification v2.3.3Compilingtauri-plugin-os v2.3.2error[E0433]:failed to resolve:could not find `MouseButton`in`tauri`-->src\lib.rs:66:49|66|...ifbutton==tauri::MouseButton::Left{|^^^^^^^^^^^could not find `MouseButton`in`tauri`|help:consider importing thisenum|2+usetauri::tray::MouseButton;|help:ifyou import `MouseButton`,refer to it directly|66-ifbutton==tauri::MouseButton::Left{66+ifbutton==MouseButton::Left{|Formore information about this error,try`rustc--explainE0433`.

把错误扔给 AI,AI 分析是包搞错了,如下:

我看到编译过程中出现了错误,问题是找不到MouseButton类型。根据错误提示,MouseButton应该来自tauri::tray 模块,而不是直接在 tauri 根模块下。

然后导入了 tray 下的 MouseButton,结果代码使用还是 tauri 包下,又搞了一轮编译不通过,最终提供了一版编译无问题,代码如下:

// 使用 Tauri 2.0 正确 API 实现所有功能usetauri::{menu::{MenuBuilder,MenuItemBuilder},tray::{MouseButton,TrayIconBuilder,TrayIconEvent},Manager,};usetauri_plugin_single_instance::initassingle_instance_init;pubfnrun(){tauri::Builder::default().plugin(tauri_plugin_os::init()).plugin(tauri_plugin_notification::init()).setup(|app|{// 1. 初始化单实例插件app.handle().plugin(single_instance_init(|app,_argv,_cwd|{// 当新实例启动时,激活现有实例的窗口ifletSome(window)=app.get_webview_window("main"){let_=window.show();let_=window.set_focus();}}))?;// 2. 获取主窗口letmain_window=matchapp.get_webview_window("main"){Some(window)=>window,None=>{eprintln!("主窗口(ID: main)未创建!");returnOk(());}};// 3. 监听窗口关闭事件letwindow_clone=main_window.clone();main_window.on_window_event(move|event|{iflettauri::WindowEvent::CloseRequested{api,..}=event{// 阻止默认关闭api.prevent_close();// 隐藏窗口let_=window_clone.hide();}});// 4. 创建托盘菜单letshow_window_item=MenuItemBuilder::new("显示主窗口").id("show_window").build(app)?;letquit_app_item=MenuItemBuilder::new("退出应用").id("quit_app").build(app)?;lettray_menu=MenuBuilder::new(app).item(&show_window_item).item(&quit_app_item).build()?;// 5. 创建系统托盘let_tray=TrayIconBuilder::new().icon(app.default_window_icon().unwrap().clone()).tooltip("时光助手").menu(&tray_menu)// 处理托盘点击事件 - 修改这里!.on_tray_icon_event(|tray,event|{matchevent{// 添加左键单击事件处理TrayIconEvent::Click{button,..}=>{ifbutton==MouseButton::Left{letapp_handle=tray.app_handle();// 获取窗口并显示ifletSome(window)=app_handle.get_webview_window("main"){let_=window.show();let_=window.set_focus();}}}// 保持双击事件处理不变TrayIconEvent::DoubleClick{..}=>{letapp_handle=tray.app_handle();// 获取窗口并显示ifletSome(window)=app_handle.get_webview_window("main"){let_=window.show();let_=window.set_focus();}}_=>{}}})// 处理菜单点击事件.on_menu_event(|tray,event|{letapp_handle=tray.app_handle();matchevent.id().as_ref(){"show_window"=>{ifletSome(window)=app_handle.get_webview_window("main"){let_=window.show();let_=window.set_focus();}}"quit_app"=>{// 退出应用app_handle.exit(0);}_=>{}}}).build(app)?;Ok(())}).run(tauri::generate_context!()).expect("运行 Tauri 应用失败");}

但是,经测试,发现还是有问题,左键点击依然会弹出菜单,快速闪烁一下后消失……

代码逻辑看上去一切正常,于是只能开启人工诊断模式。

去官网查看托盘功能相关文档:https://tauri.app/zh-cn/learn/system-tray/#%E5%88%9B%E5%BB%BA%E6%89%98%E7%9B%98%E5%9B%BE%E6%A0%87

发现官方有明确说明,默认情况下,确实单击左键会显示菜单,如下图:

按照官方说明,构建托盘的时候,设置一个属性menu_on_left_click就可以了。

手工修改,打包时提示警告,方法已过时……

warning:useof deprecated method `tauri::tray::TrayIconBuilder::<R>::menu_on_left_click`:Use`TrayIconBuilder::show_menu_on_left_click` instead.-->src\lib.rs:61:18|61|.menu_on_left_click(false)|^^^^^^^^^^^^^^^^^^|=note:`#[warn(deprecated)]` on by default

功能测试倒是正常了,终于左键不再弹出菜单了。

根据警告的提示,将属性从已废弃的menu_on_left_click,调整为show_menu_on_left_click,编译也不再报警告了,测试功能也正常。

小结

看起来一个挺简单的小问题,AI 折腾了半小时,出现了多次错误,最终也没实现预期效果。人工查阅官方文档,10 分钟就完成了处理,当然也存在一定的运气成分,刚好这个问题,官方文档里有明确说明,从警告信息来看,官方文档也陈旧了……在这种局面下,AI 也难以给出准确的答案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 16:25:41

APF+simulink仿真报告的并联型有源电力滤波器(源码+万字报告+讲解)(支持资料、图片参考_相关定制)

APFsimulink仿真报告的并联型有源电力滤波器 并联型有源电力滤波器APFsimulink仿真报告||| 利用基于瞬时无功功率理论的ip-iq谐波检测算法&#xff0c;对三相三线制并联型APF控制系统进行建模与Matlab仿真。 本文围绕并联型三相有源电力滤波器(APF)的谐波抑制与无功补偿功能展开…

作者头像 李华
网站建设 2026/6/10 15:08:01

实时OLAP解决方案:Kylin vs Druid vs ClickHouse

实时OLAP解决方案&#xff1a;Kylin vs Druid vs ClickHouse 关键词&#xff1a;实时OLAP、Kylin、Druid、ClickHouse、多维分析、列式存储、预计算Cube 摘要&#xff1a;在数据驱动决策的时代&#xff0c;实时OLAP&#xff08;在线分析处理&#xff09;是企业快速洞察数据的核…

作者头像 李华
网站建设 2026/6/10 15:31:21

大数据领域借助 Eureka 实现服务的快速定位

大数据领域借助 Eureka 实现服务的快速定位 关键词:大数据、Eureka、服务定位、微服务架构、注册中心 摘要:在大数据领域,随着系统规模的不断扩大和服务数量的急剧增加,如何快速准确地定位服务成为了一个关键问题。Eureka 作为 Netflix 开源的服务发现组件,为服务的注册与…

作者头像 李华
网站建设 2026/6/10 14:56:02

提示工程资源优化的边缘计算:架构师用边缘节点,减少云端资源消耗

提示工程资源优化实战&#xff1a;用边缘节点帮你砍半云端资源消耗 备选标题 架构师必看&#xff1a;边缘计算如何拯救提示工程的资源焦虑&#xff1f;从云端到边缘&#xff1a;提示工程资源优化的底层逻辑与实践提示工程成本优化秘籍&#xff1a;边缘节点的正确打开方式边缘计…

作者头像 李华
网站建设 2026/6/10 14:27:25

EDCA Admission Protocols 发布:AI 系统进入“可拒绝接入”时代

在现有 AI 系统中&#xff0c;一个长期被忽视却至关重要的问题正在逐渐显现&#xff1a;当人类表达进入 AI 系统时&#xff0c; 是否存在一个明确、可裁决、可拒绝的接入阶段&#xff1f;现实情况是&#xff0c;大多数系统默认“表达即执行”。 一旦输入被接收&#xff0c;就会…

作者头像 李华