【ArcGIS Pro二次开发】(45):手搓一个工具执行进度框

这篇具有很好参考价值的文章主要介绍了【ArcGIS Pro二次开发】(45):手搓一个工具执行进度框。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我在之前做的工具中,UI这部分基本没怎么深入,都是直接用现成的控件。

其中有一个问题比较突出,就是没有工具执行的进度框提示。曾经也用过系统自带的信息提示框和进度条,但太简陋,确实不好用。于是就想抄一个进度框来用,自然而然想到了ArcGIS中地理工具执行时显示的进度框:

gis运行进度条,ArcGIS,ArcGIS Pro SDK,arcgis pro,二次开发,c#,arcgis pro sdk,进度提示框

这里做一个简单版的,够用就行(其实是目前只会这些)。


一、要实现的功能

gis运行进度条,ArcGIS,ArcGIS Pro SDK,arcgis pro,二次开发,c#,arcgis pro sdk,进度提示框

进度框无法单独使用,这里结合之前做的一个【面要素拓扑】工具一起使用。

如上图所示,选择一个面要素,右键点击,在弹出的列表中点击【面要素拓扑】按钮,即可对所选要素进行处理,同时弹出一个进度提示框,实时显示目前的进程和用时。

gis运行进度条,ArcGIS,ArcGIS Pro SDK,arcgis pro,二次开发,c#,arcgis pro sdk,进度提示框

可以看出,已经和ArcGIS中地理工具的进度框有几分相似。

其实,显示用时这一点不仅对用户有帮助,对开发、测试同样是很有用的,有利于不断优化你的代码,提高代码执行效率。毕竟一个简单的功能老是显示耗时几分钟,你也很难受。


二、实现流程

1、控件选择

首先,需要确定进度框用什么来做,可以用Form,但我最终还是选择了ArcGIS ProWindow控件,毕竟已经给我们集成了更多基础性功能,用起来应该更方便。

新建一个ArcGIS ProWindow,主要的控件就2个,【ProgressBar】进度条和【RichTextBox】富文本框。

gis运行进度条,ArcGIS,ArcGIS Pro SDK,arcgis pro,二次开发,c#,arcgis pro sdk,进度提示框

【ProgressBar】用来显示当前执行进度,【RichTextBox】用来显示提示信息,包括正常流程信息和错误信息。这里使用【RichTextBox】而不是更常用的【TextBox】是考虑到显示内容需要不同字体和颜色,才能显示更丰富的文本内容,【TextBox】是无法做到的。

至于打开窗口的方法,其实【ArcGIS ProWindow】已经给我们写好了,正常创建【ArcGIS ProWindow】控件的时候,就会一起创建一个【Show*****.cs】,里面就有打开窗口的代码:

        private ProcessWindow _processwindow = null;

        protected override void OnClick()
        {
            if (_processwindow != null)
                return;
            _processwindow = new ProcessWindow();
            _processwindow.Owner = FrameworkApplication.Current.MainWindow;
            _processwindow.Closed += (o, e) => { _processwindow = null; };
            _processwindow.Show();
        }

把这部分代码抄到工具执行代码段里就行了。

2、【ArcGIS ProWindow】方法

因为上面的信息都是在【ArcGIS ProWindow】控件里显示的,所以方法都得写在ProcessWindow.xaml.cs里:

gis运行进度条,ArcGIS,ArcGIS Pro SDK,arcgis pro,二次开发,c#,arcgis pro sdk,进度提示框

这里主要需要定义3个方法:【更新进度条、添加信息文本和添加耗时文本】。

1)更新进度条

        // 变更进度条的进度【100%】
        public void AddProcess(int percent)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                pb.Value += percent;
            });
        }

这个比较简单,只要修改进度条控件的Value值即可。不过需要注意的是,操作都要在UI线程上执行,不能放在主线程里,所以需要在【Dispatcher.Invoke】下执行。

2)添加信息文本

添加信息文本需要考虑到文本的颜色和字体,所以除了文本,还添加了颜色和字体2个参数,并且设置了默认值,大部分情况下其实用默认值就行,有需要才修改参数:

        // 添加信息框文字
        public void AddMessage(string add_text, SolidColorBrush solidColorBrush = null)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                if (solidColorBrush == null)
                {
                    solidColorBrush = Brushes.Black;
                }
                // 创建一个新的TextRange对象,范围为新添加的文字
                TextRange newRange = new TextRange(tb_message.Document.ContentEnd, tb_message.Document.ContentEnd)
                {
                    Text = add_text
                };
                // 设置新添加文字的颜色
                newRange.ApplyPropertyValue(TextElement.ForegroundProperty, solidColorBrush);
                // 设置新添加文字的样式
                newRange.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Normal);
            });
        }

3)添加耗时文本

耗时信息需要计算,在工具开始执行的时候在保存一下开始时间【time_base】,然后将其作为输入参数参与计算。将新的当前时间减去【time_base】即为耗时,然后作为为文字信息写入文本框,文本颜色设为灰色,文本字体设为斜体,这部分就直接固定,不再给参数。

        // 添加信息框文字_时间
        public void AddTime(DateTime time_base)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                DateTime time_now = DateTime.Now;
                TimeSpan time_span = time_now - time_base;
                string time_total = time_span.ToString()[..time_span.ToString().LastIndexOf(".")];
                string add_text = "………………用时" + time_total + "\r";

                // 创建一个新的TextRange对象,范围为新添加的文字
                TextRange newRange = new TextRange(tb_message.Document.ContentEnd, tb_message.Document.ContentEnd)
                {
                    Text = add_text
                };
                // 设置新添加文字的颜色为灰色
                newRange.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Gray);
                // 设置新添加文字的样式为斜体
                newRange.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Italic);
            });
        }

4)组合方法

上述三个主要方法写完,其实还可以更进一步,因为正常情况下,在某一个节点,通常都不是只调用一个方法,而是多个一起调用,比如在添加文本信息的时候,同时更新进度条和上一个步骤的耗时。所以这里可以做一个方法的组合,调用的时候就可以只调用这个方法:

        // 综合显示进度【AddTime+AddMessage+AddProcess】
        public void AddProcessMessage(int percent, DateTime time_base, string add_text, SolidColorBrush solidColorBrush = null)
        {
            AddProcess(percent);
            AddTime(time_base);
            AddMessage(add_text, solidColorBrush);
        }

        // 综合显示进度【AddMessage+AddProcess】
        public void AddProcessMessage(int percent, string add_text, SolidColorBrush solidColorBrush = null)
        {
            AddProcess(percent);
            AddMessage(add_text, solidColorBrush);
        }
3、在主程序中调用【ArcGIS ProWindow】方法

直接先上完整代码:

        // 定义一个进度框
        private ProcessWindow processwindow = null;
        string tool_name = "面要素拓扑检查";

        protected override async void OnClick()
        {
			try
			{
                // 打开进度框
                ProcessWindow pw = ToolManager.OpenProcessWindow(processwindow, tool_name);
                DateTime time_base = DateTime.Now;
                pw.AddMessage("开始执行" + tool_name + "工具…………" + time_base + "\r", Brushes.Green);

                var map = MapView.Active.Map;
                // 获取默认数据库
                var gdb = Project.Current.DefaultGeodatabasePath;
                // 获取工程默认文件夹位置
                var def_path = Project.Current.HomeFolderPath;
                // 获取图层
                FeatureLayer ly = MapView.Active.GetSelectedLayers().FirstOrDefault() as FeatureLayer;
                // 如果选择的不是面要素或是无选择,则返回
                if (ly.ShapeType != esriGeometryType.esriGeometryPolygon || ly == null)
                {
                    pw.AddMessage("错误!请选择一个面要素!", Brushes.Red);
                    return;
                }
                
                string db_name = "Top2Check";    // 要素数据集名
                string fc_name = "top_fc";        // 要素名
                string top_name = "Topology";       // TOP名
                string db_path = gdb + "\\" + db_name;    // 要素数据集路径
                string fc_path = db_path + "\\" + fc_name;         // 要素路径
                string top_path = db_path + "\\" + top_name;         // TOP路径

                string err_fc = @"检查结果";
                string err_field = @"错误说明";

                await QueuedTask.Run(() =>
                {
                    pw.AddProcessMessage(10, "创建检查用的数据库和拓扑");

                    //获取图层的坐标系
                    var sr = ly.GetSpatialReference();
                    //在数据库中创建要素数据集
                    Arcpy.CreateFeatureDataset(gdb, db_name, sr);
                    // 将所选要素复制到创建的要素数据集中
                    Arcpy.CopyFeatures(ly.Name, fc_path);
                    // 新建拓扑
                    Arcpy.CreateTopology(db_path, top_name);
                    // 向拓扑中添加要素
                    Arcpy.AddFeatureClassToTopology(top_path, fc_path);
                    // 添加拓扑规则【重叠】
                    Arcpy.AddRuleToTopology(top_path, "Must Not Overlap (Area)", fc_path);
                    // 添加拓扑规则【空隙】
                    Arcpy.AddRuleToTopology(top_path, "Must Not Have Gaps (Area)", fc_path);

                    pw.AddProcessMessage(20, time_base, "生成重叠错误");

                    // 验证拓扑
                    Arcpy.ValidateTopology(top_path);
                    // 输出TOP错误
                    Arcpy.ExportTopologyErrors(top_path, gdb, "TopErr");

                    pw.AddProcessMessage(20, time_base, "生成空隙错误");

                    // 生成空隙
                    ToolManager.GetCave(fc_path, gdb + @"\" + err_fc);
                    // 添加说明字段
                    Arcpy.AddField(gdb + @"\" + err_fc, err_field, "TEXT");
                    // 空隙错误说明赋值
                    Arcpy.CalculateField(gdb + @"\" + err_fc, err_field, "'存在空隙'");
                    // 合并错误
                    Arcpy.Append(gdb + @"\TopErr_poly", gdb + @"\" + err_fc);
                    // 加载错误面图层
                    ToolManager.AddFeatureLayerToMap(gdb + @"\" + err_fc);

                    pw.AddProcessMessage(20, time_base, "生成错误标记");

                    // 重叠错误说明赋值
                    FeatureLayer init_layer = map.FindLayers(err_fc)[0] as FeatureLayer;
                    using (ArcGIS.Core.Data.Table table = init_layer.GetTable())
                    {
                        using (RowCursor rowCursor = table.Search(null, false))
                        {
                            TableDefinition tableDefinition = table.GetDefinition();
                            while (rowCursor.MoveNext())
                            {
                                using (Row row = rowCursor.Current)
                                {
                                    // 获取value
                                    var va = row[err_field];
                                    // 赋值
                                    if (va is null)
                                    {
                                        row[err_field] = "存在重叠面";
                                    }
                                    row.Store();
                                }
                            }
                        }
                    }
                    // 删除多余字段
                    Arcpy.DeleteField(err_fc, "ORIG_FID");

                    pw.AddProcessMessage(20, time_base, "应用错误图层的显示符号");

                    // 复制图层符号
                    string copy_lyrx = def_path + @"\检查结果.lyrx";
                    ToolManager.CopyResourceFile(@"CCTool.Data.Layers." + @"检查结果.lyrx", copy_lyrx);
                    // 应用图层符号
                    Arcpy.ApplySymbologyFromLayer(err_fc, copy_lyrx);

                    // 删除中间要素
                    List<string> list_del = new List<string>() { "TopErr_point", "TopErr_line", "TopErr_poly" };
                    foreach (var fc in list_del)
                    {
                        Arcpy.Delect(gdb + @"\" + fc);
                    }
                    // 删除数据集和符号图层
                    Arcpy.Delect(db_path);
                    File.Delete(copy_lyrx);

                    pw.AddProcessMessage(20, time_base, "工具运行完成!!!", Brushes.Blue);
                });
            }
			catch (Exception ee)
			{
                MessageBox.Show(ee.Message + ee.StackTrace);
				throw;
			}
        }

首先按上面【控件选择】那一节中的代码,先打开提示框。

在工具刚开始执行的时候,先生成一个初始时间,并把开始执行的信息和初始时间都添加到文本框里。

// 打开进度框
ProcessWindow pw = ToolManager.OpenProcessWindow(processwindow, tool_name);
DateTime time_base = DateTime.Now;
pw.AddMessage("开始执行" + tool_name + "工具…………" + time_base + "\r", Brushes.Green);

然后在每一个你认为需要添加信息的节点,直接调用上面写好的方法即可,如:

pw.AddProcessMessage(20, time_base, "生成重叠错误");

需要注意进度条的满值是100,这个需要自己协调好。


三、工程文件分享

 最后,放上工程文件的链接:

PrcessingFramehttps://pan.baidu.com/s/12b74CXMIs9aBJaFq_QB1fg?pwd=qz8t

PS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。文章来源地址https://www.toymoban.com/news/detail-535551.html

到了这里,关于【ArcGIS Pro二次开发】(45):手搓一个工具执行进度框的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ArcGIS Pro二次开发】(80):标注_CIMLabelClass

    CIMLabelClass(Cartographic Information Model Label Class)是ArcGIS Pro SDK中的一个类。 它主要用于定义标签的样式和属性,如字体、大小、颜色、对齐方式等,以及标签的排列和布局规则。 1、获取当前地图的标签引擎 2、修改当前地图的标签引擎 3、将文字符号TextSymbol应用到要素图层

    2024年02月19日
    浏览(50)
  • 【ArcGIS Pro二次开发】(59):Editing(编辑)模块

    ArcGIS Pro SDK中的\\\"Editing\\\"(编辑)模块提供了一系列API和工具,允许开发人员在ArcGIS Pro中实现各种地图数据编辑操作,从简单的要素绘制到复杂的数据集编辑。 下面列举一些常用编辑工具的实现方法。 1、获取所选要素的属性及赋值 2、通过【inspector】获取字段属性 3、裁剪面

    2024年02月13日
    浏览(39)
  • 【ArcGIS Pro二次开发】(56):界址点导出Excel

    界址点成果表是地籍测绘中的一种表格,用于记录地块的界址点坐标和相关属性信息。 这个工具的目的就是为了将地块要素导出为界址点成果表。 如上图所示,在【数据处理】组—【Excel相关】面板下,点击【界址点导出Excel】工具。 在弹出的工具框中,分别输入参数: 1、

    2024年02月14日
    浏览(38)
  • 【ArcGIS Pro二次开发】(36):度分秒转十进制度

    经纬度坐标的表达方式比较常用的一般有2种,【度分秒和十进制度】。 在成果展示中,以【度分秒】居多,但如果要将坐标导入ArcGIS中,则一般需要用到【十进制度】,这个转换可以在Excel中进行,也可以在ArcGIS中的字段计算里计算,但都有点小麻烦。 为了更方便的转换,

    2024年02月09日
    浏览(51)
  • 【ArcGIS Pro二次开发】(81):文本符号_CIMTextSymbol

    CIMTextSymbol是用于绘制文本图形注释的文本符号。 0、属性 Angel 文本符号的放置角度 BlockProgression 多行文本的堆叠方向 Callout 引线 DrawSoftHyphen 连字符 FlipAngle 文本翻转(镜像)到位的角度 FontEffects 上下标 FontEncoding 获取文字的Encoding FontFamilyName 字体名称 FontStyleName 字形样式,例

    2024年02月20日
    浏览(47)
  • 【ArcGIS Pro二次开发】(60):按图层导出布局

    在使用布局导图时,会遇到如下问题: 为了切换图层和导图方便,一般情况下,会把相关图层做成图层组。 在导图的时候,如果想要按照图层组进行分开导图,如上图,想导出【现状图、规划图、管控边界】3张图,系统并没有方便的工具。 于是就自己做一个。   如上图所

    2024年02月12日
    浏览(46)
  • 【ArcGIS Pro二次开发】(58):数据的本地化存储

    在做村规工具的过程中,需要设置一些参数,比如说导图的DPI,需要导出的图名等等。 每次导图前都需要设置参数,虽然有默认值,但还是需要不时的修改。 在使用的过程中,可能会有一些常用的参数,希望能够保存下来,而不是每次都去修改默认值。 于是,想到可以将这

    2024年02月14日
    浏览(44)
  • 【ArcGIS Pro二次开发】(53):村规制表、制图【福建省】

    这篇算是村规入库的一个延续。 村庄规划中有一些图纸是需要严格按照规范制图,或形成一定规范格式的。 这些图纸的制作基本算是机械式的工作,可以用工具来代替人工。 如上图所示,在【村庄规划】组,新增了两个工作面板:【制表】和【制图】。 【制表】面板共有

    2024年02月15日
    浏览(41)
  • 【ArcGIS Pro二次开发】(47):要素类追加至空库(批量)

    本工具主要是针对国空数据入库而做的。 如果你手头已经整理了一部分要素类数据,但是数据格式,字段值可能并没有完全按照规范设置好,需要将这些数据按规范批量和库,就可以尝试用这个工具。 准备数据:标准空库、你已做好的数据。 做好的数据需要把要素名改成和

    2024年02月16日
    浏览(47)
  • 【ArcGIS Pro二次开发】(49):村规数据入库【福建省】

    之前用Arcpy脚本工具做了一个村规数据入库和主要图纸生成工具。 在使用过程中,感觉对电脑环境比较高,换电脑用经常会一些莫名其妙的错误,bug修得很累。近来随着ArcGIS Pro SDK的熟悉,就有了移植的想法。 这里先把村规数据入库工具做出来,后续还将继续做主要图纸生成

    2024年02月16日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包