当前位置: 首页 > article >正文

flutter 桌面应用之右键菜单

​在 Flutter 桌面应用开发中,context_menucontextual_menu 是两款常用的右键菜单插件,各有特色。以下是对它们的对比分析:​


context_menu

  • 集成方式:​通过 ContextMenuArea 组件包裹目标组件,定义菜单项。​掘金

  • 菜单定义:​使用 builder 返回一个 List<Widget>,通常为 ListTile,支持图标、文字和点击事件。​掘金

  • 适用场景:​适合需要快速实现简单右键菜单的场景,集成方便,适用于大多数桌面应用。​掘金


contextual_menu

  • 集成方式:​需要手动监听鼠标右键事件,并调用 popUpContextualMenu() 方法显示菜单。​掘金

  • 菜单定义:​使用 MenuMenuItem 结构,支持普通项、复选框、分隔符和子菜单等多种类型。​掘金

  • 适用场景:​适合需要复杂菜单结构(如多级菜单、复选项)的应用,提供更高的自定义能力。​


总结对比

特性context_menucontextual_menu
集成方式使用组件包裹目标组件,集成简单手动监听事件,调用方法显示菜单,集成复杂
菜单结构简单,适合基本菜单复杂,支持多级菜单、复选项等
自定义能力限制较多,主要通过 ListTile 实现高度自定义,支持多种菜单项类型
适用场景快速实现基本右键菜单实现复杂、结构化的右键菜单

建议选择

  • 选择 context_menu:​如果你需要快速集成一个简单的右键菜单,且菜单项较为基础,context_menu 是一个不错的选择。​

  • 选择 contextual_menu:​如果你的应用需要复杂的菜单结构,如多级菜单、复选项等,contextual_menu 提供了更强大的功能和灵活性。

contextmenu

hello word

引入依赖

  contextmenu: ^3.0.0
import 'package:contextmenu/contextmenu.dart';
import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),),home: const MyHomePage(title: 'Flutter Demo Home Page'),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(widget.title),),body: ContextMenuArea(child: Container(color: Colors.grey,padding: EdgeInsets.all(20),child: Text("在这里右键"),),builder: (BuildContext context) {return [Container(padding: EdgeInsets.all(10), child: Text('自定义菜单')),ListTile(title: Text("点击"),onTap: () {ScaffoldMessenger.of(context,).showSnackBar(SnackBar(content: Text("点击了")));},),];},), // This trailing comma makes auto-formatting nicer for build methods.);}
}

自定义弹出位置

          ///完全自定义位置GestureDetector(onSecondaryTapDown:(details) => showContextMenu(details.globalPosition,context,(BuildContext context) {return [Container(padding: EdgeInsets.all(10),child: Text('自定义菜单'),),ListTile(title: Text("点击"),onTap: () {ScaffoldMessenger.of(context,).showSnackBar(SnackBar(content: Text("点击了")));},),];},0.0,200.0,),child: Container(padding: EdgeInsets.all(15),color: Colors.green,child: Text('Tap!'),),),

contextual_menu

hello word

https://pub.dev/packages/contextual_menu

contextual_menu: ^0.1.2
        GestureDetector(onSecondaryTapDown: (details) {Menu menu = Menu(items: [MenuItem(label: 'Copy',onClick: (_) {print('Clicked Copy');},),MenuItem(label: 'Disabled item', disabled: true),MenuItem.checkbox(key: 'checkbox1',label: 'Checkbox1',checked: true,onClick: (menuItem) {print('Clicked Checkbox1');menuItem.checked = !(menuItem.checked == true);},),MenuItem.separator(),],);popUpContextualMenu(menu, placement: Placement.bottomLeft);},child: Container(padding: EdgeInsets.all(15),color: Colors.green,child: Text('Tap!'),),),

popUpContextualMenu

可以看到我们本身没有传递position参数,那么他是怎么感知我鼠标点击的位置呢

他是通过window记录的鼠标点击位置来展示的

NSWindow.mouseLocationOutsideOfEventStream 是 macOS 平台(AppKit 框架)中的一个属性,用于获取当前鼠标在指定窗口中的坐标位置,而不是通过事件触发获取的。这个方法非常实用,尤其是在没有发生鼠标事件时,仍然需要获取当前鼠标位置的场景下。

var mouseLocationOutsideOfEventStream: NSPoint { get }

  • 返回值:一个 NSPoint,表示鼠标相对于窗口坐标系的位置。

  • 类型:NSWindow 的实例属性。

自定义ContextMenuArea


在contextmenu中我们看到ContextMenuArea包装使用非常简单,我们这里用contextual_menu也包装一个

import 'dart:ui';import 'package:contextual_menu/contextual_menu.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';typedef ContextMenuBuilder = List<MenuItem> Function(BuildContext context);class ContextualMenuArea extends StatefulWidget {final Widget child;final ContextMenuBuilder builder;const ContextualMenuArea({super.key,required this.child,required this.builder,});@overrideState<StatefulWidget> createState() {return ContextualMenuAreaState();}
}class ContextualMenuAreaState extends State<ContextualMenuArea> {bool _shouldReact = false;Offset? _position;@overrideWidget build(BuildContext context) {return Listener(child: widget.child,onPointerDown: (details) {///kSecondaryMouseButton	0x02	次键(一般是右键)///PointerDeviceKind.mouse 输入来源是鼠标_shouldReact =details.kind == PointerDeviceKind.mouse &&details.buttons == kSecondaryMouseButton;},onPointerUp: (details) {if (!_shouldReact) return;_position = details.position;_handleClickPopUp();},);}void _handleClickPopUp() {popUpContextualMenu(Menu(items: widget.builder(context)),position: _position,placement: Placement.bottomRight,);}
}

使用方式

ContextualMenuArea(child: Container(padding: EdgeInsets.all(20),color: Colors.grey,child: Text("ContextualMenuArea"),),builder: (context) {return [MenuItem.submenu(label: "复制",submenu: Menu(items: [MenuItem.checkbox(label: "复制全部", checked: false),MenuItem.checkbox(label: "复制当前", checked: true),],),),MenuItem.separator(),MenuItem(label: "粘贴"),];},)

运行效果

相关文章:

flutter 桌面应用之右键菜单

​在 Flutter 桌面应用开发中&#xff0c;context_menu 和 contextual_menu 是两款常用的右键菜单插件&#xff0c;各有特色。以下是对它们的对比分析&#xff1a;​ context_menu 集成方式&#xff1a;​通过 ContextMenuArea 组件包裹目标组件&#xff0c;定义菜单项。​掘金…...

Cygwin编译安装Acise

本文记录Windows下使用Cygwin编译安装Acise的流程。 零、环境 操作系统Windows11Visual Studio CodeVisual Studio Code 1.92.0Cygwin 一、工具及依赖 1.1 Visual Studio Code 下载并安装Visual Studio Code, 同时安装以下插件&#xff0c; Task Explorer Output Colorizer …...

基于STM32、HAL库的IP6525S快充协议芯片简介及驱动程序设计

一、简介: IP6525S是一款高性能的同步降压DC-DC转换器芯片,具有以下特点: 输入电压范围:4.5V至32V 输出电压范围:0.8V至30V 最大输出电流:5A 效率高达95% 可编程开关频率(100kHz-1MHz) 支持PWM和PFM模式 内置过流保护、过温保护等功能 该芯片常用于工业控制、通信设备…...

RabbitMQ惰性队列的工作原理、消息持久化机制、同步刷盘的概念、延迟插件的使用方法

惰性队列工作原理 惰性队列通过尽可能多地将消息存储到磁盘上来减少内存的使用。与传统队列相比&#xff0c;惰性队列不会主动将消息加载到内存中&#xff0c;而是尽量让消息停留在磁盘上&#xff0c;从而降低内存占用。尽管如此&#xff0c;它并不保证所有操作都是同步写入磁…...

MySQL与Oracle深度对比

MySQL与Oracle深度对比&#xff1a;数据类型与SQL差异 一、数据类型差异 1. 数值类型对比 数据类型MySQLOracle整数TINYINT, SMALLINT, MEDIUMINT, INT, BIGINTNUMBER(精度) 或直接INT(内部仍为NUMBER)小数DECIMAL(p,s), FLOAT, DOUBLENUMBER(p,s), FLOAT, BINARY_FLOAT, BI…...

【Leetcode 每日一题】1922. 统计好数字的数目

问题背景 我们称一个数字字符串是 好数字 当它满足&#xff08;下标从 0 0 0 开始&#xff09;偶数 下标处的数字为 偶数 且 奇数 下标处的数字为 质数 ( 2 , 3 , 5 (2, \ 3, \ 5 (2, 3, 5 或 7 ) 7) 7)。 比方说&#xff0c;“2582” 是好数字&#xff0c;因为偶数下标处…...

pyqtgraph.opengl.items.GLSurfacePlotItem.GLSurfacePlotItem 报了一个错

1. 需求是这个样子的 有一个 pyqtgraph.opengl.GLViewWidget &#xff0c;在应用启动时存在QMainWindow中&#xff0c;即父对象是QMainWindow&#xff0c;当业务需要时&#xff0c;修改它的父对象变为一个QDialog&#xff0c;可以让它从QMainWindow中弹出显示在QDialog里&#…...

【C++初学】课后作业汇总复习(六) 函数模板

1、函数模板 思考&#xff1a;如果重载的函数&#xff0c;其解决问题的逻辑是一致的、函数体语句相同&#xff0c;只是处理的数据类型不同&#xff0c;那么写多个相同的函数体&#xff0c;是重复劳动&#xff0c;而且还可能因为代码的冗余造成不一致性。 解决&#xff1a;使用…...

【第16届蓝桥杯C++C组】--- 数位倍数

Hello呀&#xff0c;小伙伴们&#xff0c;第16届蓝桥杯也完美结束了&#xff0c;无论大家考的如何&#xff0c;都要放平心态&#xff0c;今年我刚上大一&#xff0c;也第一次参加蓝桥杯&#xff0c;刷的算法题也只有200来道&#xff0c;但是还是考的不咋滴&#xff0c;但是拿不…...

ASP.NET Core 性能优化:客户端响应缓存

文章目录 前言一、什么是缓存二、客户端缓存核心机制&#xff1a;HTTP缓存头1&#xff09;使用[ResponseCache]属性&#xff08;推荐&#xff09;2&#xff09;预定义缓存配置&#xff08;CacheProfile&#xff09;3&#xff09;手动设置HTTP头4&#xff09;缓存验证机制&#…...

Numpy和OpenCV库匹配查询,安装OpenCV ABI错误

文章目录 地址opencv-python&#xff1a;4.x版本的对应numpyopencv-python&#xff1a;5.x版本的对应numpy方法2 ps&#xff1a;装个opencv遇到ABI错误无语了&#xff0c;翻了官网&#xff0c;github文档啥都没&#xff0c;记录下 地址 opencv-python&#xff1a;4.x版本的对应…...

全球变暖(蓝桥杯 2018 年第九届省赛)

题目描述 你有一张某海域 NN 像素的照片&#xff0c;. 表示海洋、 # 表示陆地&#xff0c;如下所示&#xff1a; ....... .##.... .##.... ....##. ..####. ...###. .......其中 "上下左右" 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。 由…...

ubuntu18.04安装miniforge3

1.下载安装文件 略&#xff08;注&#xff1a;从同事哪里拖来的安装包&#xff09; 2.修改安装文件权限 chmod x Miniforge3-Linux-x86_64.sh 3.将它安装到指定位置 micromamba activate /home/xxx/fxp/fromDukto/miniforge3 4.激活 /home/xxx/fxp/fromDukto/miniforge3…...

高并发短信系统设计:基于SharingJDBC的分库分表、大数据同步与实时计算方案

高并发短信系统设计&#xff1a;基于SharingJDBC的分库分表、大数据同步与实时计算方案 一、概述 在当今互联网应用中&#xff0c;短信服务是极为重要的一环。面对每天发送2000万条短信的需求&#xff0c;我们需要一个能够处理海量数据&#xff08;一年下来达到数千万亿级别&…...

OceanBase企业版集群部署:oatcli命令行方式

OceanBase企业版集群部署&#xff1a;oatcli命令行方式 安装包准备服务器准备最低资源配置是否部署ODP组件&#xff1f;仲裁服务器 服务器配置操作系统内核参数BIOS设置磁盘挂载网卡设置 安装OAT部署工具初始化OBServer服务器使用oatcli部署三副本集群安装OceanBase软件初始化O…...

SQL 查询中涉及的表及其作用说明

SQL 查询中涉及的表及其作用说明&#xff1a; 涉及的数据库表 表名别名/用途关联关系dbo.s_orderSO&#xff08;主表&#xff09;存储订单主信息&#xff08;订单号、日期、客户等&#xff09;dbo.s_orderdetailSoD&#xff08;订单明细&#xff09;通过 billid SO.billid 关…...

智能手机功耗测试

随着智能手机发展,用户体验对手机的续航功耗要求越来越高。需要对手机进行功耗测试及分解优化,将手机的性能与功耗平衡。低功耗技术推动了手机的用户体验。手机功耗测试可以采用powermonitor或者NI仪表在功耗版上进行测试与优化。作为一个多功能的智能终端,手机的功耗组成极…...

UNIX域套接字(Unix Domain Sockets, UDS) 的两种接口

目录 1. 流式套接字&#xff08;SOCK_STREAM&#xff09;特点类比典型使用场景代码示例&#xff08;伪代码&#xff09; 2. 数据报套接字&#xff08;SOCK_DGRAM&#xff09;特点类比典型使用场景代码示例&#xff08;伪代码&#xff09; 3. 两者的核心区别对比4. 为什么 UNIX …...

使用U盘安装 ubuntu 系统

1. 准备U 盘制作镜像 1.1 下载 ubuntu iso https://ubuntu.com/download/ 这里有多个版本以供下载&#xff0c;本文选择桌面版。 1.2 下载rufus https://rufus.ie/downloads/ 1.3 以管理员身份运行 rufus 设备选择你用来制作启动项的U盘&#xff0c;不能选错了&#xff1b;点…...

安全厂商安全理念分析

奇安信&#xff08;toB企业安全&#xff09; 安全理念&#xff1a;率先提出 “内生安全” 理念。即把安全能力内置到信息化环境中&#xff0c;通过信息化系统和安全系统的聚合、业务数据和安全数据的聚合、IT 人才和安全人才的聚合&#xff0c;让安全系统像人的免疫系统一样&a…...

Redis如何判断哨兵模式下节点之间数据是否一致

在哨兵模式下判断两个Redis节点的数据一致性&#xff0c;可以通过以下几种方法实现&#xff1a; 一、检查主从复制偏移量 使用INFO replication命令 分别在主节点和从节点执行该命令&#xff0c;比较两者的master_repl_offset&#xff08;主节点&#xff09;和slave_repl_offs…...

HarmonyOS-ArkUI V2装饰器: @Provider和@Consumer装饰器:跨组件层级双向同步

作用 我们在之前学习的那些控件中,各有特点,也各有缺陷,至今没有痛痛快快的出现过真正能跨组件的双向绑定的装饰器。 比如 @Local装饰器,不能跨组件@Param装饰器呢,能跨组件传递,但是仅仅就是下一层组件接收参数。另外,它是单向传递,不可被重新赋值。如果您非要改值则…...

oracle 并行度(Parallel Degree)

在Oracle数据库中&#xff0c;并行度&#xff08;Parallel Degree&#xff09; 是用于控制并行处理任务的关键配置&#xff0c;旨在通过多进程协作加速大规模数据处 一、并行度的核心概念 并行度&#xff08;DOP, Degree of Parallelism&#xff09; 表示一个操作同时使用的并…...

Redis-场景缓存+秒杀+管道+消息队列

缓存一致性 1.两次更新 先更新数据库&#xff0c;再更新缓存&#xff1b;先更新缓存&#xff0c;再更新数据库&#xff1b; 出现不一致问题场景&#xff1a; 先更新数据库&#xff0c;再更新缓存&#xff1b; 先更新缓存&#xff0c;再更新数据库&#xff1b; 两次更新的适…...

系统的安全及应用

仓库做了哪些优化 仓库源换成国内源不使用root用户登录将不必要的开机启动项关闭内核的调优 系统做了哪些安全加固 禁止使用root禁止使用弱命令将常见的 远程连接端口换掉 系统安全及应用 Cpu负载高 java程序 运行异常中病毒&#xff1f; ps aux - - sort %cpu %mem Cpu …...

PostgreSQL内幕探索—基础知识

PostgreSQL内幕探索—基础知识 PostgreSQL&#xff08;以下简称PG&#xff09; 起源于 1986 年加州大学伯克利分校的 ‌POSTGRES 项目‌&#xff0c;最初以对象关系模型为核心&#xff0c;支持高级数据类型和复杂查询功能‌。 1996 年更名为 PostgreSQL 并开源&#xff0c;逐…...

基于redis 实现我的收藏功能优化详细设计方案

基于redis 实现我的收藏功能优化详细设计方案 一、架构设计 +---------------------+ +---------------------+ | 客户端请求 | | 数据存储层 | | (收藏列表查询) | | (Redis Cluster) | +-------------------…...

WPS复制粘贴错误 ,文件未找到 mathpage.wll

文章目录 1.错误提示图片2.解决方案1.找到MathType.wll文件和MathType Commands 2016.dotm文件并复制2.找到wps安装地址并拷贝上述两个文件到指定目录 3.重启WPS 1.错误提示图片 2.解决方案 1.找到MathType.wll文件和MathType Commands 2016.dotm文件并复制 MathType.wll地址如…...

驱动开发硬核特训 · Day 6 : 深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比

&#x1f50d; B站相应的视屏教程&#xff1a; &#x1f4cc; 内核&#xff1a;博文视频 - 从静态绑定驱动模型到现代设备模型 主题&#xff1a;深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比 在上一节中&#xff0c;我们从驱动框架的历史演进出…...

【UE5 C++课程系列笔记】35——HTTP基础——HTTP客户端异步请求API接口并解析响应的JSON

目录 前言 步骤 一、 搭建异步蓝图节点框架 二、异步蓝图节点嵌入到引擎的执行流程 三、获取本地时间并异步返回 四、获取网络时间并异步返回 五、源码 前言 本文以请求网络/本地时间API为例&#xff0c;介绍如何实现HTTP异步请求。 步骤 一、 搭建异步蓝图节点框架 …...