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

news/2024/11/30 7:38:06/

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

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

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


一、要实现的功能

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

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

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

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


二、实现流程

1、控件选择

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

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

【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里:

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

1)更新进度条

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

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

2)添加信息文本

添加信息文本需要考虑到文本的颜色和字体,所以除了文本,还添加了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){// 获取valuevar 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,这个需要自己协调好。


三、工程文件分享

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

PrcessingFrameicon-default.png?t=N5K3https://pan.baidu.com/s/12b74CXMIs9aBJaFq_QB1fg?pwd=qz8t

PS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。


http://www.ppmy.cn/news/691842.html

相关文章

C++图形开发(1):graphics图形库简介与安装

文章目录 1.引入2.安装&#xff08;1&#xff09;在官网下载安装包&#xff08;2&#xff09;安装 3.检验 1.引入 为了帮助大家实现真正的、更有意思的C开发&#xff0c;本人决定开一个C图形开发的专栏&#xff0c;来制作更多的有意思的游戏、程序。 首先我们要了解的&#x…

新手简单看懂Servlet里面的web.xml配置

背景&#xff1a; ecplisetomcatservlet 我们在学习servlet时候&#xff0c;因为前面基础没学好&#xff0c;导致servlet看不懂&#xff0c;比如笔者当时就是servlet的web.xml看不懂&#xff0c;如果我们能先看懂web.xml&#xff0c;知道前端访问哪个接口&#xff0c;调用哪个…

JavaScript的try-catch-finally异常处理机制--详解

JavaScript 提供了异常处理机制&#xff0c;通过 try-catch-finally 语句块来捕获和处理异常。以下是对该机制的详细解释和示例&#xff1a; 1. try 块&#xff1a; try 块用于包裹可能会产生异常的代码块。在 try 块内&#xff0c;您可以放置任何可能引发异常的代码。 2. ca…

佳能打印机手机显示未连接服务器,安装佳能LBP1210打印机 提示RPC服务器不可用,该怎办/...

楼主应对情况做出更加具体的描述&#xff0c;以待更好地解决此问题&#xff0c;下面是一般情况下解决此类问题的方法&#xff0c;您可以尝试看能不能解决&#xff1a; 症状 在执行下列任一基于服务器的任务时&#xff0c;可能收到“RPC server is unavailable(RPC服务器不可用)…

佳能hdr_佳能650D支持HDR吗

佳能650D支持HDR功能&#xff0c;原理是在连续拍摄曝光不足、曝光标准、曝光过度3张图像&#xff0c;最终合成一张宽广动态范围的照片。 佳能650D是一款APS画幅单反数码相机&#xff0c;采用新开发的约1800万有效像素CMOS图像感应器&#xff0c;在约22.314.9毫米的有效空间内合…

最长回文串

Manacher 问题 寻找字符串中的最长回文串 传统做法 字符串首字符前加一个特殊字符 ‘#’ 末尾字符加一个特殊字符 ‘#’ 相邻字符间也加上特殊字符 ‘#’ 遍历字符串&#xff0c;除特殊字符外&#xff0c;以每个字符作为回文字符串的中心向外扩张 思考 很明显这种做法的…

Java程序所在机器性能监控

Java程序所在机器性能监控 背景 问题单&#xff1a;程序故障&#xff08;OOM、网络不通、操作卡顿&#xff09;问题单&#xff1a;服务连接不上需求 1、监控本地机器性能 告警日志UI2、监控服务接口服务 告警日志UI方案 固定间隔获取机器网络CPU内存数据设置阈值&#xff0c;告…

探探提醒对方账号异常_我告诉你探探账号异常不能回复消息怎么办

解决方法&#xff1a;有多种原因&#xff0c;如果是账号被封&#xff0c;无法回复短信&#xff1b;如果是网络异常导致&#xff0c;建议切换网络再回复&#xff1b;如果是软件出现bug&#xff0c;可以进行反馈&#xff0c;在探探3.7.5版本中&#xff0c;打开软件&#xff0c;点…