Flutter桌面应用程序定义系统托盘Tray

文章目录

  • 概念
  • 实现方案
    • 1. tray_manager
      • 依赖库
      • 支持平台
      • 实现步骤
    • 2. system_tray
      • 依赖库
      • 支持平台
      • 实现步骤
    • 3. 两种方案对比
    • 4. 注意事项
    • 5. 话题拓展

概念

系统托盘:系统托盘是一种用户界面元素,通常出现在操作系统的任务栏或桌面顶部。它是一个水平的狭长区域,用于显示各种图标和通知,以提供快速访问和操作特定应用程序或系统功能。系统托盘通常包含操作系统或第三方应用程序的图标,这些图标可以显示有关应用程序状态、提醒和通知等信息。用户可以通过单击这些图标来打开应用程序的主窗口、执行特定功能或查看详细信息。系统托盘的设计旨在提供一种方便的方式来管理和访问常用的应用程序和系统功能,以提高用户的工作效率。
效果展示
在这里插入图片描述

作为现代操作系统中常见的一个组件,系统托盘能够让用户方便地访问常用的应用程序或者系统功能。对于Flutter桌面应用程序开发者来说,如何在应用程序中定义系统托盘是一个值得探讨的问题。本文将简介系统托盘的概念,并介绍两种可用的Flutter桌面应用程序系统托盘方案。

实现方案

1. tray_manager

依赖库

tray_manager

支持平台

Windows, macOS & Linux

实现步骤

  1. 在pubspec.yaml中添加依赖
dependencies:...tray_manager: ^0.2.0
  1. 导入依赖
import 'package:flutter/material.dart' hide MenuItem;
import 'package:tray_manager/tray_manager.dart';
  1. 配置系统托盘特性
Future<void> _init() async {//设置系统托盘图标,Windows图标必须文件后缀必须是.icoawait trayManager.setIcon(Platform.isWindows? 'assets/images/tray_icon_original.ico': 'assets/images/img_1.png',);//设置系统托盘的标题trayManager.setTitle("system tray");//设置系统托盘的标题trayManager.setToolTip("How to use system tray with Flutter:鼠标滑过提示");//设置系统托盘的菜单Menu menu = Menu(items: [//设置系统托盘的子菜单MenuItem.submenu(// key key: 'window_settings',label: '窗口设置',//trayManager 不支持菜单项添加图标,该配置无效icon: Platform.isWindows? 'assets/images/app_icon.bmp': 'assets/images/img_1.png',submenu: Menu(items: [MenuItem.checkbox(checked: true,label: "毛玻璃效果",onClick: (MenuItem menuItem) {menuItem.checked = !(menuItem.checked == true);if (kDebugMode) {print("毛玻璃效果 onClick ${menuItem.checked}");}},),MenuItem.checkbox(checked: true,label: "窗口置顶",onClick: (MenuItem menuItem) {menuItem.checked = !(menuItem.checked == true);if (kDebugMode) {print("窗口置顶 onClick ${menuItem.checked}");}},),MenuItem.checkbox(checked: true,label: "自启动",onClick: (MenuItem menuItem) {menuItem.checked = !(menuItem.checked == true);if (kDebugMode) {print("自启动 onClick ${menuItem.checked}");}},),//可选类型的菜单栏MenuItem.checkbox(checked: true,label: "图标闪烁",onClick: (MenuItem menuItem) {menuItem.checked = !(menuItem.checked == true);if (kDebugMode) {print("图标闪烁 onClick ${menuItem.checked}");}},),])),//分割线MenuItem.separator(),MenuItem(key: 'open_app',label: 'Open App',onClick: (MenuItem menuItem) {}),MenuItem(key: 'exit_app',label: 'Exit App',onClick: (MenuItem menuItem) {}),],);if (kDebugMode) {print("menu:${menu.toJson()}");}//为系统托盘配置菜单await trayManager.setContextMenu(menu);
}
  1. 监听TrayListener
import 'package:flutter/material.dart';
import 'package:tray_manager/tray_manager.dart';class HomePage extends StatefulWidget {_HomePageState createState() => _HomePageState();
}class _HomePageState extends State<HomePage> with TrayListener {void initState() {trayManager.addListener(this);super.initState();_init();}void dispose() {trayManager.removeListener(this);super.dispose();}void _init() {// ...}Widget build(BuildContext context) {// ...}
//未触发该事件
void onTrayIconRightMouseUp() {// TODO: implement onTrayIconRightMouseUpsuper.onTrayIconRightMouseUp();if (kDebugMode) {print("onTrayIconMouseUp");}
}//未触发该事件

void onTrayIconMouseUp() {super.onTrayIconMouseUp();if (kDebugMode) {print("onTrayIconMouseUp");}
}

void onTrayIconMouseDown() {if (kDebugMode) {print("onTrayIconMouseDown");}//弹出托盘的菜单栏trayManager.popUpContextMenu();
}
void onTrayIconRightMouseDown() {if (kDebugMode) {print("onTrayIconRightMouseDown");}//弹出托盘的菜单栏trayManager.popUpContextMenu();
}//弹出托盘的菜单栏点击事件

void onTrayMenuItemClick(MenuItem menuItem) {if (kDebugMode) {print("menuItem:${menuItem.key}-${menuItem.label}");}
}
}

2. system_tray

依赖库

system_tray

支持平台

Windows, macOS & Linux

实现步骤

  1. 在pubspec.yaml中添加依赖
dependencies:...system_tray: ^2.0.3
  1. 导入依赖
import 'package:system_tray/system_tray.dart';
  1. 配置系统托盘特性
//创建SystemTray 对象
final SystemTray _systemTray = SystemTray();
Timer? _timer;//配置系统托盘
Future<void> _initSystemTray() async {//设置系统托盘的图标,必须是.ico后缀的图片await _systemTray.initSystemTray(iconPath: Platform.isWindows? 'assets/images/tray_icon_original.ico': 'assets/images/img_1.png',);//设置系统托盘的标题_systemTray.setTitle("system tray");//设置系统托盘的提示_systemTray.setToolTip("How to use system tray with Flutter");//注册系统托盘事件_systemTray.registerSystemTrayEventHandler((eventName) {debugPrint("eventName: $eventName");//注册系统托盘事件:点击事件if (eventName == kSystemTrayEventClick) {//Windows系统:显示主窗口   其他系统弹出托盘菜单弹框Platform.isWindows? windowManager.show(): _systemTray.popUpContextMenu();//注册系统托盘事件:鼠键右键} else if (eventName == kSystemTrayEventRightClick) {//Windows系统:弹出托盘菜单弹框  其他系统: 显示主窗口Platform.isWindows? _systemTray.popUpContextMenu(): windowManager.show();}});//创建托盘的菜单final Menu _menuMain = Menu();await _menuMain.buildFrom([//创建子菜单SubMenu(label: "窗口设置",//创建为菜单子项添加图标,格式必须是bmpimage: Platform.isWindows? 'assets/images/app_icon.bmp': 'assets/images/img_1.png',children: [//创建可选框类型的菜单项MenuItemCheckbox(label: "毛玻璃效果",checked: true,name: 'acrylic_cb',onClicked: (MenuItemBase menuItem) async {//更新MenuItemCheckbox的状态await menuItem.setCheck(!menuItem.checked);if (kDebugMode) {print("毛玻璃效果 onClick ${menuItem.checked}");}if (menuItem.checked == true) {showAcrylic(color);} else {closeAcrylic();}}),MenuItemCheckbox(label: "窗口置顶",checked: true,onClicked: (MenuItemBase menuItem) async {await menuItem.setCheck(!menuItem.checked);if (kDebugMode) {print("窗口置顶 onClick ${menuItem.checked}");}if (menuItem.checked == true) {windowManager.setAlwaysOnTop(true);} else {windowManager.setAlwaysOnTop(false);}}),MenuItemCheckbox(label: "自启动",checked: true,name: 'auto_start_cb',onClicked: (MenuItemBase menuItem) async {// menuItem.checked = !(menuItem.checked == true);await menuItem.setCheck(!menuItem.checked);if (kDebugMode) {print("自启动 onClick ${menuItem.checked}");}}),MenuItemCheckbox(label: "图标闪烁",checked: true,name: "flash_cb",onClicked: (MenuItemBase menuItem) async {MenuItemCheckbox? flashCb =_menuMain.findItemByName<MenuItemCheckbox>("flash_cb");await flashCb?.setCheck(!menuItem.checked);if (kDebugMode) {print("图标闪烁 onClick ${menuItem.checked}");}if (menuItem.checked) {startFlashIcon();} else {stopFlashIcon();}}),]),//菜单分割线MenuSeparator(),//菜单项MenuItemLabel(label: 'Open App',image: Platform.isWindows? 'assets/images/app_icon.bmp': 'assets/images/img_1.png',onClicked: (MenuItemBase menuItem) {windowManager.show();}),MenuItemLabel(label: 'Exit App',image: Platform.isWindows? 'assets/images/app_icon.bmp': 'assets/images/img_1.png',onClicked: (MenuItemBase menuItem) {windowManager.close();}),]);if (kDebugMode) {print("menu:${_menuMain.toString()}");}//为系统托盘设置菜单项await _systemTray.setContextMenu(_menuMain);
}
  1. 完整代码
import 'package:flutter/material.dart';
import 'package:tray_manager/tray_manager.dart';class HomePage extends StatefulWidget {_HomePageState createState() => _HomePageState();
}class _HomePageState extends State<HomePage>  {Timer? _timer;final SystemTray _systemTray = SystemTray();void initState() {super.initState();_initSystemTray();}void dispose() {_timer.cancel();super.dispose();}void _initSystemTray() {// ...}//开始图标闪烁
void startFlashIcon() {if (kDebugMode) {print("startFlashIcon");}var imageList = const ["assets/images/tray_icon_original.ico","assets/images/tray_icon.ico"];var index = 0;_timer =Timer.periodic(const Duration(milliseconds: 500), (Timer timer) async {if (kDebugMode) {print("path:${imageList[index]}");}await _systemTray.setImage(imageList[index]);index = (index == 0) ? 1 : 0;});
}//停止图标闪烁
void stopFlashIcon() async {if (kDebugMode) {print("stopFlashIcon");}_timer?.cancel();_timer = null;await _systemTray.setImage("assets/images/tray_icon_original.ico");
}Widget build(BuildContext context) {// ...}
}

3. 两种方案对比

   system_tray 支持菜单项添加图标,tray_manager不支持菜单项添加图标

4. 注意事项

Windows平台系统托盘图标需要是以.ico后缀的图片,菜单项图标需要是.bmp后缀的图片,否则图片无法显示;

5. 话题拓展

  • BMP格式(Bitmap):BMP是一种无损的位图图像格式,最初由Microsoft开发。它可以存储图像的像素颜色和位置信息,并支持不同的色彩深度。BMP文件通常较大,因为它们不经过压缩,保留了图像的每个像素的完整信息。BMP格式适用于Windows系统和一些图像编辑软件。
  • ICO格式(Icon):ICO是一种用于存储图标的文件格式。ICO文件通常用于表示计算机系统上的各种图标,例如文件夹、应用程序和网站等的图标。ICO文件可以包含多个图标大小和颜色深度的版本,以适应不同的显示需求。ICO文件可以在Windows系统中直接使用,也可以在网页或应用程序中使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/200833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习在单线性回归方程中的应用--TensorFlow实战详解

深度学习在单线性回归方程中的应用–TensorFlow实战详解 文章目录 深度学习在单线性回归方程中的应用--TensorFlow实战详解1、人工智能<-->机器学习<-->深度学习2、线性回归方程3、TensorFlow实战解决单线性回归问题人工数据集生成构建模型训练模型定义损失函数定义…

发请求/传递过程中出现‘[object Object]‘的问题“

问题&#xff1a;post请求的时候data数据传过去的的时候显示data: [object Object] 问题代码&#xff1a; wx.request( { url: "", header: { "Content-Type": "application/x-www-form-urlencoded" }, method: "POST", data:…

【算法每日一练]-图论(保姆级教程篇11 tarjan模板篇)无向图的桥 #无向图的割点 #有向图的强连通分量

目录 预备知识 模板1&#xff1a;无向图的桥 模板2&#xff1a;无向图的割点 模板3&#xff1a;有向图的强连通分量 讲之前先补充一下必要概念&#xff1a; 预备知识 无向图的【连通分量】&#xff1a; 即极大联通子图&#xff0c;再加入一个节点就不再连通&#xff08;对…

Python 删除字典列表等元素问题

""" 在 Python 中&#xff0c;在迭代列表的同时修改它可能导致意外的结果&#xff0c; 因为这会破坏迭代器的状态。在你的代码中&#xff0c;当你尝试删除元素时&#xff0c; 迭代器可能会跳过下一个元素&#xff0c;导致删除的不是你预期的元素。 ""…

Kafka Schema介绍

Avro概述 简介 Apache Avro(以下简称 Avro,读音:阿夫罗)是一个数据序列化系统,是一种与编程语言无关的序列化格式,是提供一种共享数据文件的方式。Avro是Hadoop中的一个子项目,Avro是一个基于二进制数据传输高性能的中间件。Avro可以做到将数据进行序列化,适用于远程…

三星AI笔电:年底大战一触即发,行业变革在即

随着科技的不断发展&#xff0c;人工智能&#xff08;AI&#xff09;已逐渐渗透至我们日常生活的各个角落&#xff0c;而其在电脑行业的应用也正引发一场革命。 据韩国媒体Businesskorea报道&#xff0c;全球科技巨头三星电子即将于12月中发表世界首款搭载AI技术的笔电。此次发…

Leetcode1423. 可获得的最大点数

Every day a Leetcode 题目来源&#xff1a;1423. 可获得的最大点数 解法1&#xff1a;前缀和 后缀和 基于贪心的思想&#xff0c;要使得获得的点数最大&#xff0c;每次拿卡牌都应该选点数尽量高的卡牌。 但是拿卡牌有限制&#xff0c;每次行动&#xff0c;只可以从行的…

[Java][项目][战斗逻辑]基于JFrame的文字游戏

项目注解&#xff1a; Core:启动文件 AttributeBean&#xff1a;玩家属性 BackpackedBean&#xff1a;背包设计&#xff08;未完成&#xff09; BackpackedFrame&#xff1a;背包页面&#xff08;未完成&#xff09; BattleField&#xff1a;战斗逻辑&#xff08;核心&…

Android Chips(标签)

目录 一、流式布局标签发展历程 二、类型及使用 2.1 Chip.Action(默认值) 2.2 Chip.Entry 2.3 Chip.Filter 2.4 Chip.Choice 三、常用事件 3.1 OnClickListener 3.2 OnCheckedChangeListener 3.3 OnCloseIconClickListener 四、ChipGroup 4.1 ChipGroup Chip.Choi…

AGI = 大模型 + 知识图谱 + 强化学习

一、大模型&#xff08;Large Models&#xff09; 定义&#xff1a; 大模型通常指的是参数数量庞大的机器学习模型&#xff0c;特别是深度学习模型。这些模型在训练时需要大量的计算资源和数据。例如&#xff0c;GPT-3&#xff08;Generative Pre-trained Transformer 3&#…

力扣973. 最接近原点的 K 个点(java 排序法,大顶堆法)

Problem: 973. 最接近原点的 K 个点 文章目录 题目描述思路解题方法复杂度Code 题目描述 给定一个数组 points &#xff0c;其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点&#xff0c;并且是一个整数 k &#xff0c;返回离原点 (0,0) 最近的 k 个点。 这里&#xff0c;平面…

获取网络ppt资源

背景&#xff1a; ​ 某度上有很多优质的PPT资源和文档资源&#xff0c;但是大多数需要付费才能获取。对于一些经济有限的用户来说&#xff0c;这无疑是个遗憾&#xff0c;因为我们更倾向于以免费的方式获取所需资源。 解决方案&#xff1a; ​ 然而&#xff0c;幸运的是&am…

python 笔记:将不同长度2D矩阵线性插值至相同长度(scipy.interpolate)

1 问题描述 我现在有三个2D矩阵&#xff0c;每一行是两个元素&#xff0c;代表经纬度&#xff1b;不同矩阵的行数不同 现在希望通过线性插补&#xff0c;使得每个2D矩阵行数相同 pth_lst[[[1,2],[1,3],[3,4]],[[3,4],[5,6],[7,8],[9,10],[11,12],[13,14],[15,16]],[[2,4],[5…

记录一次driud连接池的连接数用完问题

一、问题描述&#xff1a; 最直观的表现就是生产上项目崩了&#xff0c;无法访问。 二、分析原因&#xff1a; 通过查看生产日志&#xff0c;出现了大量的获取连接超时异常&#xff0c;具体如下&#xff1a; org.springframework.jdbc.CannotGetJdbcConnectionException:Fail…

Python 网络爬虫(四):初识网络爬虫

《Python入门核心技术》专栏总目录・点这里 文章目录 什么是爬虫爬虫的工作原理应用场景反爬虫合法和道德问题Robots 协议练习爬虫的一些网站总结 大家好&#xff0c;我是水滴~~ 在当今数字化时代&#xff0c;互联网上充斥着大量的数据和信息&#xff0c;而我们常常需要从这个…

vue运用之echart柱状图3D效果案例代码

前言 在ECharts中,创建3D柱状图需要使用GL模块,并设置type为’bar3D’ 柱状图案例可参考,我的这篇文章 Echarts之柱状图 3D柱状图的示例代码 // 引入ECharts主模块 var echarts = require(echarts); // 引入3D模块 var GL = require(echarts/util/graphic/GL

思维模型 移情效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。情感迁移&#xff0c;爱屋及乌。 1 移情效应的应用 1.1 移情效应在市场营销中应用-多芬&#xff08;Dove&#xff09;“真美运动” 多芬&#xff08;Dove&#xff09;是一家知名的个人护理…

软件工程 复习笔记

目录 概述 软件的定义&#xff0c;特点和分类 软件的定义 软件的特点 软件的分类 软件危机的定义和表现形式 软件危机 表现形式 软件危机的产生原因及解决途径 产生软件危机的原因 软件工程 概念 软件工程的研究内容和基本原理 内容 软件工程的基本原理 软件过程…

Redis使用Lua脚本

Lua脚本 redis可以支持lua脚本&#xff0c;可以使用lua脚本来将几个命令整合为一个整体来执行&#xff0c;这样可以使得多个命令原子操作&#xff0c;且可以减少网络开销 Lua的数据类型 Lua是一个动态类型的语言&#xff0c;一个变量可以存储任何类型的值&#xff0c;类型有&am…

27、卷积 - 卷积特征的可视化和一个神奇的网站

既然上一节说了卷积的本质是一个特征提取器,那么既然卷积神经网络在图像分类、图像检测、图像分割以及其他领域有这么好的表现,卷积算法到底提取了什么特征呢? 虽然有时候我们说神经网络是个黑盒,但是研究人员也一直在探索,如何将卷积学习到的特征给分析出来。 就是想要…