HalconToolAdvancedEditor.xaml.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using System;
  2. using System.Threading.Tasks;
  3. using System.Windows;
  4. using HalconDotNet;
  5. using TeamAAS.FlowEditor.Models;
  6. using TeamAAS.FlowEditor.Plugins;
  7. using TeamAAS.FlowEngine;
  8. using TeamAAS.Vision;
  9. namespace Plugins.Halcon.Views
  10. {
  11. /// <summary>
  12. /// HALCON 算子专用高级编辑窗体(普通编辑=属性面板常用参数;高级编辑=本窗体):
  13. /// - 左侧参数面板:同一套模型属性(PropertyGridLib),改完即生效;
  14. /// - 右侧大显示窗:HalconWindow(缩放/平移/ROI 绘制/保存),运行结果经图层总线渲染;
  15. /// - 加载图像:从文件载入测试图并注册为流程「图像」输入变量(算子绑定 &{输入.图像} 时直接生效);
  16. /// - 执行:用当前流程注册表跑一遍该算子(与画布运行同一执行路径),状态栏回报结果与耗时。
  17. /// 窗体非模态(可边看流程边调参)。
  18. /// </summary>
  19. public partial class HalconToolAdvancedEditor : Window
  20. {
  21. private readonly BasePluginModel _model;
  22. private readonly HalconWindow _display;
  23. private IFlowNodePlugin _plugin;
  24. private bool _running;
  25. /// <summary>打开算子高级编辑窗体(非模态)。</summary>
  26. public static void Show(BasePluginModel model)
  27. {
  28. if (model == null) return;
  29. var win = new HalconToolAdvancedEditor(model);
  30. win.Show();
  31. win.Activate();
  32. }
  33. public HalconToolAdvancedEditor(BasePluginModel model)
  34. {
  35. InitializeComponent();
  36. _model = model;
  37. TxtTitle.Text = $"{model.ToolName ?? "Halcon 算子"} · {model.NodeName}";
  38. Title = $"高级编辑 - {model.ToolName ?? model.GetType().Name}";
  39. // 普通参数面板(与属性面板同一套模型,双向实时同步)
  40. PropertyHost.Content = new PropertyGridLib.PropertyGrid { SelectedObject = model };
  41. // 大显示窗
  42. _display = new HalconWindow(1);
  43. _display.SetCaption(model.ToolName ?? "预览");
  44. DisplayHost.Content = _display;
  45. // 图层总线:该算子发布图层 → 渲染(整组:底图+叠加,区域自动附带原图)
  46. VisionLayerStore.Instance.LayerPublished += OnLayerPublished;
  47. Closed += (s, e) => VisionLayerStore.Instance.LayerPublished -= OnLayerPublished;
  48. }
  49. /// <summary>算子插件实例(懒创建;挂当前流程注册表,公式/输入变量按流程上下文解析)。</summary>
  50. private IFlowNodePlugin Plugin
  51. {
  52. get
  53. {
  54. if (_plugin == null)
  55. {
  56. _plugin = PluginLoader.Instance.CreateInstance(_model.ToolName);
  57. if (_plugin != null)
  58. {
  59. _plugin.GetModel = _model;
  60. _plugin.Registry = PluginLoader.Instance.SelectFlow?.Registry;
  61. }
  62. }
  63. return _plugin;
  64. }
  65. }
  66. /// <summary>该算子发布图层 → 整组渲染(含区域附带原图回退)。</summary>
  67. private void OnLayerPublished(LayerPublishArgs args)
  68. {
  69. if (args == null || _model == null) return;
  70. if (!string.Equals(args.FlowId, _model.FlowId, StringComparison.OrdinalIgnoreCase)) return;
  71. if (!string.Equals(args.NodeName, _model.NodeName, StringComparison.OrdinalIgnoreCase)) return;
  72. try
  73. {
  74. Dispatcher.Invoke(() =>
  75. {
  76. var layers = LayerComboHelper.ResolveLayers(args, null, args.FlowId);
  77. if (layers.Count > 0) _display.ShowLayers(layers);
  78. });
  79. }
  80. catch { }
  81. }
  82. /// <summary>执行:后台线程跑一遍该算子(不卡 UI),完成回报状态与耗时。</summary>
  83. private void BtnRun_Click(object sender, RoutedEventArgs e)
  84. {
  85. if (_running) return;
  86. var plugin = Plugin;
  87. if (plugin == null)
  88. {
  89. TxtStatus.Text = "创建插件实例失败(检查插件是否加载)";
  90. return;
  91. }
  92. _running = true;
  93. BtnRun.IsEnabled = false;
  94. TxtStatus.Text = "执行中…";
  95. Task.Run(() =>
  96. {
  97. try
  98. {
  99. var status = plugin.Run(System.Threading.CancellationToken.None);
  100. SetStatus($"执行完成: {status},耗时 {plugin.CostTime}ms");
  101. }
  102. catch (Exception ex)
  103. {
  104. SetStatus("执行失败: " + ex.Message);
  105. }
  106. finally
  107. {
  108. try { Dispatcher.Invoke(() => { _running = false; BtnRun.IsEnabled = true; }); } catch { }
  109. }
  110. });
  111. }
  112. /// <summary>加载测试图像:注册为流程「图像」输入变量并立即预览。</summary>
  113. private void BtnLoadImage_Click(object sender, RoutedEventArgs e)
  114. {
  115. var dlg = new Microsoft.Win32.OpenFileDialog
  116. {
  117. Filter = "图像文件|*.png;*.jpg;*.jpeg;*.bmp;*.tif;*.tiff|所有文件|*.*",
  118. Title = "加载测试图像"
  119. };
  120. if (dlg.ShowDialog(this) != true) return;
  121. try
  122. {
  123. HOperatorSet.ReadImage(out HObject img, dlg.FileName);
  124. var registry = PluginLoader.Instance.SelectFlow?.Registry;
  125. if (!string.IsNullOrEmpty(_model.FlowId))
  126. registry?.SetInputVariable(_model.FlowId, "图像", img);
  127. _display.RefreshImage(img);
  128. TxtStatus.Text = registry != null
  129. ? "已加载图像并注册为输入变量「图像」"
  130. : "已加载图像(未找到流程注册表,仅预览)";
  131. }
  132. catch (Exception ex)
  133. {
  134. TxtStatus.Text = "加载失败: " + ex.Message;
  135. }
  136. }
  137. private void SetStatus(string message)
  138. {
  139. try { Dispatcher.Invoke(() => TxtStatus.Text = message); } catch { }
  140. }
  141. }
  142. }