C#为复杂属性提供下拉式编辑框和弹出式编辑框

一.为属性提供编辑类

  弹出式和下拉式是如何实现的呢,这需要为属性提供一个专门的编辑类。.Net为我们提供了一个System.Drawing.Design.UITypeEditor类,它是所有编辑类的基类,从他继承出了诸如ColorEditor、FontEditor的类,因此我们可以在属性框中编辑颜色和字体。定义了这样的类,我们也可以为自己的属性实现弹出式和下拉式编辑方式。

  先看一下MSDN中对UITypeEditor的介绍:提供可用于设计值编辑器的基类,这些编辑器可提供用户界面 (UI),用来表示和编辑所支持的数据类型的对象值。

 UITypeEditor 类提供一种基类,可以从该基类派生和进行扩展,以便为设计时环境实现自定义类型编辑器。通常,您的自定义类型编辑器与 PropertyGrid 控件进行交互。在文本框值编辑器不足以有效地选择某些类型的值的情况下,自定义类型编辑器非常有用。

 

继承者说明:若要实现自定义设计时 UI 类型编辑器,必须执行下列步骤

using System;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;public class MyCustomEditor : UITypeEditor
{// 1. 指定编辑器样式:Modal 表示使用弹出对话框public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)// 2. 处理属性值的编辑public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)// 3. 支持绘制值的表示形式public override bool GetPaintValueSupported(ITypeDescriptorContext context)// 4. 绘制值的表示形式public override void PaintValue(PaintValueEventArgs e)//5 .设置默认值或执行其他初始化逻辑public MyCustomEditor() }

1. 定义一个从 UITypeEditor 派生的类

  • 目的:创建一个新的编辑器类,用于自定义编辑属性值的方式。
  • 步骤:从 UITypeEditor 基类继承,通常会定义一个新类,例如 MyCustomEditor

2. 重写 EditValue 方法

  • 目的:处理用户界面和用户输入操作,以及对属性值的分配。

  • 步骤:在 EditValue 方法中,你将实现弹出对话框或其他用户界面,允许用户输入新值,然后将这个值应用到目标属性上。例如:

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value){ // 实现自定义编辑逻辑 // 例如,显示对话框让用户输入新值 // 更新并返回新的值}

3. 重写 GetEditStyle 方法

  • 目的:通知“属性”窗口该编辑器使用的编辑器样式。

  • 步骤GetEditStyle 方法返回一个 UITypeEditorEditStyle 枚举值,指示编辑器的类型(如 UITypeEditorEditStyle.ModalUITypeEditorEditStyle.DropDownUITypeEditorEditStyle.None)。例如:

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
    { return UITypeEditorEditStyle.Modal; // 或其他适当的样式
    }

4. 支持值的表示形式(可选)

  • 目的:在属性窗口中显示值的可视化表示形式。

  • 步骤:实现这部分功能时,你需要:

    • 重写 GetPaintValueSupported 方法:指示编辑器是否支持显示值的表示形式。返回 true 表示支持,false 表示不支持。

      public override bool GetPaintValueSupported(ITypeDescriptorContext context) 
      { return true; // 表示支持绘制值的表示形式 
      }
    • 重写 PaintValue 方法:实现如何绘制值的表示形式。例如,你可以绘制一个图标或图像,代表属性的当前值。

      public override void PaintValue(PaintValueEventArgs e) 
      { 
      // 实现绘制逻辑 
      // 例如绘制一个矩形来显示颜色值 
      e.Graphics.FillRectangle(new SolidBrush(Color.Red),e.Bounds); 
      }

5. 初始化行为(可选)

  • 目的:如果编辑器需要特定的初始化行为,你可以重写 UITypeEditor 的构造函数。

  • 步骤:在自定义构造函数中,你可以设置默认值或执行其他初始化逻辑。

    public MyCustomEditor() 
    { // 实现初始化逻辑 }

这些步骤为你提供了创建和自定义 UITypeEditor 的基础,以便在设计时属性窗口中更好地管理和展示属性值。

 

 接下来我们来实现下拉式编辑方式,接下来举一个具体的例子来说明:

  首先假如我们有一个控件类MyControl:

public class MyControl : System.Windows.Forms.UserControl
{private double _angle;[BrowsableAttribute(true)]public double Angle{get{ return _angle; }set{ _angle = value; }}public MyControl(){this._angle = 90;}protected override void OnPaint(System.Windows.Forms.PaintEventArgs e){e.Graphics.DrawString("The Angle is " + _angle, this.Font, Brushes.Red,0,0);}
}

其中有个属性Angle,我们要为其提供下拉式和弹出式编辑方式,当然了,一般都是较为复杂的属性才需要,这里只是为了举例说明。

二.下拉式编辑方式 

  我们为其定义一个派生的编辑类AngleEditor,EditValue和GetEditStyle两个函数,这是必须要重写的:

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]public class AngleEditor : System.Drawing.Design.UITypeEditor
{public AngleEditor(){}//下拉式还是弹出式public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context){return UITypeEditorEditStyle.DropDown;}// 为属性显示UI编辑框public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value){//值类型不为double,直接返回valueif (value.GetType() != typeof(double))return value;//值为double,显示下拉式或弹出编辑框IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));if (edSvc != null){// 显示编辑框并初始化编辑框的值AngleControl angleControl = new AngleControl((double)value);edSvc.DropDownControl(angleControl);// 返回编辑框中编辑的值.if (value.GetType() == typeof(double))return angleControl.angle;}return value;}//下面两个函数是为了在PropertyGrid中显示一个辅助的效果//可以不用重写public override void PaintValue(System.Drawing.Design.PaintValueEventArgs e){int normalX = (e.Bounds.Width / 2);int normalY = (e.Bounds.Height / 2);e.Graphics.FillRectangle(new SolidBrush(Color.DarkBlue), e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);e.Graphics.FillEllipse(new SolidBrush(Color.White), e.Bounds.X + 1, e.Bounds.Y + 1, e.Bounds.Width - 3, e.Bounds.Height - 3);e.Graphics.FillEllipse(new SolidBrush(Color.SlateGray), normalX + e.Bounds.X - 1, normalY + e.Bounds.Y - 1, 3, 3);double radians = ((double)e.Value * Math.PI) / (double)180;e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), 1), normalX + e.Bounds.X, normalY + e.Bounds.Y,e.Bounds.X + (normalX + (int)((double)normalX * Math.Cos(radians))),e.Bounds.Y + (normalY + (int)((double)normalY * Math.Sin(radians))));}public override bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context){return true;}}// 这里是我们要显示出来的编辑器,把它作为一个内置类,本质上他就是一个显示form//从UserControl继承,要在上面EditValue函数中使用的internal class AngleControl : System.Windows.Forms.UserControl{public double angle; //编辑的角度private float x;     //鼠标位置private float y;public AngleControl(double initial_angle){this.angle = initial_angle;}//显现时,显示属性的当前值protected override void OnLoad(EventArgs e){int originX = (this.Width / 2);int originY = (this.Height / 2);this.x = (float)(50 * Math.Cos(this.angle * Math.PI / 180) + originX);this.y = (float)(50 * Math.Sin(this.angle * Math.PI / 180) + originY);base.OnLoad(e);}//绘制控件,用来显示编辑角度protected override void OnPaint(System.Windows.Forms.PaintEventArgs e){int originX = (this.Width / 2);int originY = (this.Height / 2);e.Graphics.DrawEllipse(Pens.Black, originX - 50, originY - 50, 100, 100);e.Graphics.DrawLine(Pens.Black, originX, originY, x, y);e.Graphics.DrawString("Angle:" + this.angle, this.Font, Brushes.Red, 0, 0);}//鼠标移动时设置角度protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e){if (e.Button == MouseButtons.Left){int originX = (this.Width / 2);int originY = (this.Height / 2);double len = Math.Sqrt(Math.Pow(e.X - originX, 2) + Math.Pow(e.Y - originY, 2));double h = e.Y - originY;this.angle = Math.Asin(h / len);if ((e.X >= originX && e.Y >= originY)){this.x = (float)(50 * Math.Cos(this.angle) + originX);this.y = (float)(50 * Math.Sin(this.angle) + originY);this.angle = this.angle * 180 / Math.PI;}else if (e.X < originX && e.Y > originY){this.x = (float)(originX - 50 * Math.Cos(this.angle));this.y = (float)(50 * Math.Sin(this.angle) + originY);this.angle = 180 - this.angle * 180 / Math.PI;}else if (e.X < originX && e.Y < originY){this.x = (float)(originX - 50 * Math.Cos(this.angle));this.y = (float)(originY + 50 * Math.Sin(this.angle));this.angle = 180 - this.angle * 180 / Math.PI;}else if (e.X >= originX && e.Y <= originY){this.x = (float)(originX + 50 * Math.Cos(this.angle));this.y = (float)(originY + 50 * Math.Sin(this.angle));this.angle = 360 + this.angle * 180 / Math.PI;}this.Invalidate();}          }      
}

这里有两个类,一个是AngleEditor,他就是我们要用于到属性特性中的编辑类,一个是AngleControl,他是辅助AngleEditor来编辑属性的,也就是说,他就是一个form,当我们编辑属性时,他会显现出来,供我们编辑属性值,可以是textBox,图形,表格,各种方式,只需要最后他返回编辑好的属性值给AngleEditor类。在AngleEditor类中的EditValue函数中,我们会调用AngleControl类,并接受它返回的值。

  设计好编辑类后,把它应用到MyControl类中的Angle属性中,在Angle属性中增加特性[EditorAttribute(typeof(AngleEditor), typeof(System.Drawing.Design.UITypeEditor))],相当于告诉PropertyGrid我们要用AngleEditor来编辑这个属性。  

[BrowsableAttribute(true)]
[EditorAttribute(typeof(AngleEditor), typeof(System.Drawing.Design.UITypeEditor))]
public double Angle
{get{ return _angle; }set{ _angle = value; }
}

效果如下:

三.弹出式编辑方式

  实现了下拉式,我们来实现弹出式,弹出式和下拉式非常的相像,现在要弹出一个编辑框,因此我们的AngleControl类不能从UserControl继承,而从From继承,让他成为一个对话框,在AngleEditor的EditValue函数中,弹出他并接受返回值,如下:

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]public class AngleEditor : System.Drawing.Design.UITypeEditor
{public AngleEditor(){}//下拉式还是弹出式.//这里是第一个修改的地方,改为了弹出式。public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context){return UITypeEditorEditStyle.Modal;//弹出式}// 为属性显示UI编辑框public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value){//值类型不为double,直接返回valueif (value.GetType() != typeof(double))return value;//值为double,显示下拉式或弹出编辑框IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));if (edSvc != null){// 显示编辑框并初始化编辑框的值,//这里是第二个修改点,改为showDialogAngleControl2 angleControl = new AngleControl2((double)value);edSvc.ShowDialog(angleControl);                // 返回编辑框中编辑的值.if (value.GetType() == typeof(double))return angleControl.angle;}return value;}//下面两个函数是为了在PropertyGrid中显示一个辅助的效果//可以不用重写public override void PaintValue(System.Drawing.Design.PaintValueEventArgs e){int normalX = (e.Bounds.Width / 2);int normalY = (e.Bounds.Height / 2);e.Graphics.FillRectangle(new SolidBrush(Color.DarkBlue), e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);e.Graphics.FillEllipse(new SolidBrush(Color.White), e.Bounds.X + 1, e.Bounds.Y + 1, e.Bounds.Width - 3, e.Bounds.Height - 3);e.Graphics.FillEllipse(new SolidBrush(Color.SlateGray), normalX + e.Bounds.X - 1, normalY + e.Bounds.Y - 1, 3, 3);double radians = ((double)e.Value * Math.PI) / (double)180;e.Graphics.DrawLine(new Pen(new SolidBrush(Color.Red), 1), normalX + e.Bounds.X, normalY + e.Bounds.Y,e.Bounds.X + (normalX + (int)((double)normalX * Math.Cos(radians))),e.Bounds.Y + (normalY + (int)((double)normalY * Math.Sin(radians))));}public override bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context){return true;}}// 这里是我们要显示出来的编辑器,把它作为一个内置类//从UserControl继承,要在上面EditValue函数中使用的//这里是第三个修改点,让他显示为对话框,所以继承了form类internal class AngleControl2 : System.Windows.Forms.Form{public double angle; //编辑的角度private float x;     //鼠标位置private float y;public AngleControl(double initial_angle){this.angle = initial_angle;}//显现时,显示属性的当前值protected override void OnLoad(EventArgs e){int originX = (this.Width / 2);int originY = (this.Height / 2);this.x = (float)(50 * Math.Cos(this.angle * Math.PI / 180) + originX);this.y = (float)(50 * Math.Sin(this.angle * Math.PI / 180) + originY);base.OnLoad(e);}//绘制控件,用来显示编辑角度protected override void OnPaint(System.Windows.Forms.PaintEventArgs e){int originX = (this.Width / 2);int originY = (this.Height / 2);e.Graphics.DrawEllipse(Pens.Black, originX - 50, originY - 50, 100, 100);e.Graphics.DrawLine(Pens.Black, originX, originY, x, y);e.Graphics.DrawString("Angle:" + this.angle, this.Font, Brushes.Red, 0, 0);}//鼠标移动时设置角度protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e){if (e.Button == MouseButtons.Left){int originX = (this.Width / 2);int originY = (this.Height / 2);double len = Math.Sqrt(Math.Pow(e.X - originX, 2) + Math.Pow(e.Y - originY, 2));double h = e.Y - originY;this.angle = Math.Asin(h / len);if ((e.X >= originX && e.Y >= originY)){this.x = (float)(50 * Math.Cos(this.angle) + originX);this.y = (float)(50 * Math.Sin(this.angle) + originY);this.angle = this.angle * 180 / Math.PI;}else if (e.X < originX && e.Y > originY){this.x = (float)(originX - 50 * Math.Cos(this.angle));this.y = (float)(50 * Math.Sin(this.angle) + originY);this.angle = 180 - this.angle * 180 / Math.PI;}else if (e.X < originX && e.Y < originY){this.x = (float)(originX - 50 * Math.Cos(this.angle));this.y = (float)(originY + 50 * Math.Sin(this.angle));this.angle = 180 - this.angle * 180 / Math.PI;}else if (e.X >= originX && e.Y <= originY){this.x = (float)(originX + 50 * Math.Cos(this.angle));this.y = (float)(originY + 50 * Math.Sin(this.angle));this.angle = 360 + this.angle * 180 / Math.PI;}this.Invalidate();}}}

 

可以看到,只修改了三个地方:

1.AngleEditor类中GetEditStyle函数返回Modal,表明是以弹出式编辑。

2.AngleEditor类中EditValue函数中调用编辑控件的方式:

      AngleControl2 angleControl = new AngleControl2((double)value);
      edSvc.ShowDialog(angleControl);    

3.AngleControl2从Form继承,让他显示为对话框,这里为了区别上面的AngleControl类,将其改成了AngleControl2。

效果如下:

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

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

相关文章

B. 不知道该叫啥

题意&#xff1a;求长度为n的数列方案数&#xff0c;数列需满足两个条件&#xff1a;1.均为正整数。2.相邻两个数乘积不能超过m 思路&#xff1a;考虑dp。 设表示前i个点以j结尾的方案数&#xff0c;则有&#xff1a; 可以得出&#xff1a; 双指针数论分块解决。把每个m/i相…

基于STM32开发的智能水箱液位控制系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 系统初始化液位监测与控制水泵控制与状态显示Wi-Fi通信与远程监控应用场景 家庭用水系统的液位控制工业水箱的液位管理常见问题及解决方案 常见问题解决方案结论 1. 引言 智能水箱液位控制系…

一种简单视觉处理

背景 网友说他有个芯片的图&#xff0c;识别不出管脚的位置 俺就写了一个代码&#xff0c;识别管脚的位置&#xff0c;先看结果。 代码 识别图片&#xff0c;并显示结果&#xff0c;对于结果位置使用红色标出 PT pt new PT();pt.Find(bmp);Bitmap bmp_tmp new Bitmap(bmp);…

GPT-4、Claude 3 Opus 和 Gemini 1.0 Ultra 挑战控制工程的新领域

介绍 论文地址&#xff1a;https://arxiv.org/abs/2404.03647 近年来&#xff0c;GPT-4、Claude 3 Opus 和 Gemini 1.0 Ultra 等大规模语言模型&#xff08;LLM&#xff09;迅速发展&#xff0c;展示了它们解决复杂问题的能力。LLM 的这些发展在多个领域都有潜在的应用前景。…

Adobe After Effects的插件--------CC Ball Action

CC Ball Action是粒子效果器,其将2D图层变为一个个由3D小球构成的图层。它是AE内置的3D插件。 使用条件 使用该插件的图层需是2D图层。 我们以一张图片素材为例: 给图片图层添加CC Ball Action效果控件,然后新建一个摄像机(利用摄像机旋转、平移、推拉工具,方便在各个角…

探究Python中的函数与模块

一、引言 随着程序的复杂度增加&#xff0c;代码的组织与重用性就显得尤为重要。为了编写更加结构化、易于维护的代码&#xff0c;函数和模块的使用是必不可少的。 函数是Python中最基本的代码组织形式&#xff0c;通过将代码封装成函数&#xff0c;我们可以实现代码的重用、…

C++不同数据类型连接成一个字符串

在C中数据连接的方式使用号进行连接。 1.都是字符型时直接使用连接几个字符串&#xff1b; 2.不是字符类型时&#xff0c;要用to_string函数转换后再连接。

【C语言】浮点型数据在内存中的储存

浮点型数据在内存中的储存 文章目录 浮点型数据在内存中的储存引例概念提出浮点型数据储存规定对于有效数字M的特别规定对于指数E的特别规定指数E的储存指数E的读取 利用规则解释原因 在之前学习过整形数据在内存中的储存后&#xff0c;浮点型数据在内存中的储存又会怎样呢&…

android 实现简易音乐播放器

音乐App 源代码 &#xff1a; 简易音乐APP源代码 1、简介 一个简易的音乐APP&#xff0c;主要练习对四大组件的应用。感兴趣的可以看看。 播放界面如下&#xff1a; 歌曲列表界面如下&#xff1a; 项目结构如下&#xff1a; 接下来将对代码做详细介绍&#xff1a; 2、Musi…

Leetcode876. 链表的中间结点(双指针)

题目描述 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&#xff1a;链表只有一个中…

【蓝桥杯冲刺省一,省一看这些就够了-C++版本】蓝桥杯C++STL及相关练习题

蓝桥杯历年省赛真题 点击链接免费加入题单 STL map及其函数 map<key,value> 提供一对一的数据处理能力&#xff0c;由于这个特性&#xff0c;它完成有可能在我们处理一对一数据的时候&#xff0c;在编程上提供快速通道。map 中的第一个值称为关键字(key)&#xff0c;…

python 多进程 多线程 程序

这个纯粹为了增加理解&#xff0c;将很多比较好的资料进行归纳总结。 1、理论汇总 并发和并行 image.png 多进程和多线程 同步和异步 同步&#xff1a;所谓同步&#xff0c;就是在发出一个功能调用时&#xff0c;在没有得到结果之前&#xff0c;该调用就不会返回。 异步…

C语言刷题日记(附详解)(2)

一、有理数加法 输入格式&#xff1a; 输入在一行中按照a1/b1 a2/b2的格式给出两个分数形式的有理数&#xff0c;其中分子和分母全是整形范围内的正整数。 输出格式&#xff1a; 在一行中按照a/b的格式输出两个有理数的和。注意必须是该有理数的最简分数形式&#xff0c;若…

​14:00面试,14:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

Linux系统下的容器安全:深入解析与最佳实践

在云计算和微服务架构的推动下&#xff0c;容器技术因其高效、可移植和灵活的特点&#xff0c;已经成为现代软件开发和部署的首选方案。然而&#xff0c;容器的广泛应用也带来了新的安全挑战&#xff0c;尤其是在Linux系统下&#xff0c;容器安全的实现和维护变得尤为重要。本文…

如何使用python脚本爬取微信公众号文章?

1、什么是爬虫&#xff1f; 在座的各位可能经常听到一个词&#xff0c;叫“爬虫”&#xff0c;这是一种能够悄无声息地将网站数据下载至本地设备的程序。利用爬虫&#xff0c;您无需亲自访问特定网站&#xff0c;逐个点击并手动下载所需数据。相反&#xff0c;爬虫能够全自动地…

STM32——PWM波形输出

一、IC和OC 可以看到&#xff1a;定时器除了基本的定时中断功能&#xff0c;输入捕获、输出比较均是STM32定时器的功能 输入捕获IC&#xff08;Input Capture&#xff09; 输入捕获是一种用于测量外部信号脉冲宽度或频率的技术。它通过定时器模块捕获外部信号的特定事件&…

2024年AI编程新手必备工具,快速提升技能!

在当今这个技术日新月异的时代&#xff0c;AI编程已成为一个越来越重要的领域&#xff0c;吸引着众多新手和希望提升自己的中级开发者进入。 对于这些渴望在AI领域快速成长的人来说&#xff0c;选择合适的编程工具是至关重要的。 接下来&#xff0c;我们将深入探讨几款市场上…

Aria2安装和使用-Mac版

起因是需要网盘下载&#xff0c;无奈限速很烦&#xff0c;查找很多方案后&#xff0c;最终决定使用Aria2 Tampermonkey。 其中Aria2是一款开源轻量的下载软件&#xff0c;简单来说就是可以通过URL直接下载。 Tampermonkey则是一款插件&#xff0c;我这里是.crx结尾的谷歌插件…

抢单源码修正版,带教程,自动抓取订单,十几种语言可自动切换

亚马逊抢单源码自动抓取订单任务邀请英文,西班牙语可自动切换语言亲测修正版。带完整开源的前后台。 西班牙,英文&#xff0c;巴西&#xff0c;中文&#xff0c;德国&#xff0c;拉法兰西&#xff0c;荷兰&#xff0c;缅甸&#xff0c;Sverige&#xff0c;日本&#xff0c;Trk…