Tauri2 系统托盘开发实战:Gisvip地图下载器托盘功能实现

Tauri   2026-01-27 15:53   90   0  

在开发 Gisvip 地图下载器的过程中,用户可通过托盘快速唤起窗口或退出程序。本文将详细拆解 Tauri 中系统托盘的创建、配置与功能实现,分享从基础用法到完整实战的全过程。

一、核心依赖与基础概念

Tauri 提供了 @tauri-apps/api/tray 模块用于实现系统托盘,核心类为 TrayIcon;搭配 @tauri-apps/api/menu 可实现托盘右键菜单,@tauri-apps/api/window 则用于窗口状态的控制(显示、置顶、解除最小化等)。

路径规则注意:托盘图标 icon 的相对路径基于项目根目录下的 src-tauri/ 文件夹,这是 Tauri 各类资源路径的通用规则。

二、基础功能实现

1. 创建基础托盘

先实现最简易的托盘创建,仅初始化托盘实例,后续可逐步扩展配置:

import { TrayIcon } from '@tauri-apps/api/tray';

const options = {
  // 可在此配置图标、菜单、事件等核心参数
};

const tray = await TrayIcon.new(options);

2. 自定义托盘图标

为托盘设置自定义图标,只需在 options 中指定 icon 路径,替换为自己的图标文件即可:

import { TrayIcon } from '@tauri-apps/api/tray';

const options = {
  icon: "icons/32x32.png", // 路径基于 src-tauri/
};

const tray = await TrayIcon.new(options);

3. 添加托盘右键菜单

通过 Menu 类创建右键菜单,可自定义菜单项的文本、点击事件,同时控制左键点击是否触发菜单:

import { TrayIcon } from '@tauri-apps/api/tray';
import { Menu } from '@tauri-apps/api/menu';

// 创建右键菜单
const menu = await Menu.new({
  items: [
    {
      id: 'quit',
      text: '退出',
      action: () => {
        console.log('quit pressed');
      },
    },
  ],
});

const options = {
  menu,
  menuOnLeftClick: false, // 禁用左键显示菜单(默认true,左键/右键均触发)
};

const tray = await TrayIcon.new(options);

三、完整实战:带窗口控制的托盘实现

以下是 Gisvip 地图下载器中托盘的完整实现代码,包含「显示窗口」「退出程序」核心功能,以及左键唤起窗口、右键菜单的完整逻辑:

1. 核心函数封装

// 获取当前窗口
import { getCurrentWindow } from '@tauri-apps/api/window';
// 导入系统托盘相关
import { TrayIcon, TrayIconOptions, TrayIconEvent } from '@tauri-apps/api/tray';
// 托盘菜单
import { Menu } from '@tauri-apps/api/menu';
import { getName } from '@tauri-apps/api/app';

/**
 * 窗口置顶并显示(处理隐藏/最小化状态)
 */
const winShowFocus = async () => {
  const win = getCurrentWindow();
  // 窗口不可见则显示
  if (!(await win.isVisible())) {
    win.show();
  } else {
    // 最小化则解除最小化
    if (await win.isMinimized()) {
      await win.unminimize();
    }
    // 窗口置顶聚焦
    await win.setFocus();
  }
};

/**
 * 创建托盘右键菜单
 */
const createMenu = async () => {
  return await Menu.new({
    items: [
      {
        icon: 'icons/32x32.png',
        id: 'show',
        text: '显示窗口',
        action: () => {
          winShowFocus();
        },
      },
      {
        id: 'quit',
        text: '退出',
        action: async () => {
          try {
            await getCurrentWindow().close(); // 关闭窗口并退出程序
          } catch (error) {
            console.error('退出程序失败:', error);
          }
        },
      },
    ],
  });
};

/**
 * 初始化系统托盘
 */
export const createTray = async () => {
  const options: TrayIconOptions = {
    // 托盘图标(路径基于 src-tauri/)
    icon: 'icons/32x32.png',
    // 悬浮提示文本(获取应用名称)
    tooltip: await getName(),
    // 禁用左键显示菜单(左键用于唤起窗口)
    menuOnLeftClick: false,
    // 托盘图标事件处理
    action: (event: TrayIconEvent) => {
      // 监听左键按下事件
      if (event.type === 'Click' && event.button === 'Left' && event.buttonState === 'Down') {
        winShowFocus(); // 唤起并置顶窗口
      }
    },
  };

  // 挂载右键菜单
  options.menu = await createMenu();
  // 创建托盘实例
  await TrayIcon.new(options);
};

2. 调用初始化托盘

在 Vue 组件(如 App.vue)的挂载阶段调用 createTray,完成托盘初始化:

<script setup lang="ts">
import { onMounted } from 'vue';
import { createTray } from './utils/tray'; // 引入封装的托盘函数

onMounted(() => {
  createTray()
    .then(() => {
      console.log('系统托盘创建成功');
    })
    .catch((error) => {
      console.error('托盘创建失败:', error);
    });
});
</script>


博客评论