BGA辅助面板:气泡/焊球模式切换、VoidLimit面板调节、去掉标签右键编辑、未完成组气泡可拖拽调整
This commit is contained in:
@@ -394,6 +394,23 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
public void SetBubbleBrushSize(int val) => _bubbleBrushSize = val;
|
||||
public Rect? BubbleRoi => _bubbleRoi;
|
||||
|
||||
/// <summary>设置 BGA 测量的气泡/焊球绘制模式</summary>
|
||||
public void SetBgaDrawBall(bool drawBall)
|
||||
{
|
||||
_bgaDrawBall = drawBall;
|
||||
RaiseMeasureStatusChanged(drawBall ? "BGA - 画焊球模式" : "BGA - 画气泡模式");
|
||||
}
|
||||
|
||||
/// <summary>设置所有 BGA 组的 VoidLimit 并刷新标签</summary>
|
||||
public void SetBgaVoidLimit(double limit)
|
||||
{
|
||||
foreach (var g in _bgaGroups)
|
||||
{
|
||||
g.VoidLimit = limit;
|
||||
g.UpdateLabel();
|
||||
}
|
||||
}
|
||||
|
||||
// 拖拽状态
|
||||
private Ellipse _mDraggingDot;
|
||||
private object _mDraggingOwner;
|
||||
@@ -722,9 +739,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
{
|
||||
_bgaCurrent = new Models.BgaVoidGroup();
|
||||
var currentGroup = _bgaCurrent; // 局部变量供闭包捕获
|
||||
_bgaCurrent.Label = new TextBlock { FontSize = 13, FontWeight = FontWeights.Bold, Cursor = System.Windows.Input.Cursors.Hand, Visibility = Visibility.Collapsed };
|
||||
_bgaCurrent.Label.SetValue(ContextMenuService.IsEnabledProperty, false);
|
||||
_bgaCurrent.Label.PreviewMouseRightButtonUp += (s, ev) => { ShowBgaLimitEditor(currentGroup); ev.Handled = true; };
|
||||
_bgaCurrent.Label = new TextBlock { FontSize = 13, FontWeight = FontWeights.Bold, IsHitTestVisible = false, Visibility = Visibility.Collapsed };
|
||||
_measureOverlay.Children.Add(_bgaCurrent.Label);
|
||||
_bgaDrawBall = false;
|
||||
RaiseMeasureStatusChanged("BGA空隙 - 点击画气泡圆心(右键切换为画焊球)");
|
||||
@@ -924,10 +939,12 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
if (g.E4BH == dot) { _mDraggingOwner = g; _mDraggingRole = "E4B"; break; }
|
||||
}
|
||||
}
|
||||
// 查找 BGA 组
|
||||
// 查找 BGA 组(已完成的 + 正在编辑的)
|
||||
if (_mDraggingOwner == null)
|
||||
{
|
||||
foreach (var g in _bgaGroups)
|
||||
var allBga = new System.Collections.Generic.List<Models.BgaVoidGroup>(_bgaGroups);
|
||||
if (_bgaCurrent != null) allBga.Add(_bgaCurrent);
|
||||
foreach (var g in allBga)
|
||||
{
|
||||
if (g.Ball?.CenterDot == dot) { _mDraggingOwner = g; _mDraggingRole = "BallCenter"; break; }
|
||||
if (g.Ball?.EdgeDot == dot) { _mDraggingOwner = g; _mDraggingRole = "BallEdge"; break; }
|
||||
|
||||
@@ -492,11 +492,29 @@ namespace XplorePlane.ViewModels
|
||||
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.ThroughHoleFillRate);
|
||||
}
|
||||
|
||||
private Window _bgaMeasurePanel;
|
||||
|
||||
private void ExecuteBgaVoidMeasure()
|
||||
{
|
||||
if (!CheckImageLoaded()) return;
|
||||
_logger.Info("BGA空隙测量功能已触发");
|
||||
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.BgaVoid);
|
||||
|
||||
if (_bgaMeasurePanel != null && _bgaMeasurePanel.IsVisible)
|
||||
{
|
||||
_bgaMeasurePanel.Activate();
|
||||
return;
|
||||
}
|
||||
|
||||
_bgaMeasurePanel = new Views.ImageProcessing.BgaMeasurePanel
|
||||
{
|
||||
Owner = System.Windows.Application.Current.MainWindow
|
||||
};
|
||||
_bgaMeasurePanel.Closed += (s, e) =>
|
||||
{
|
||||
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.None);
|
||||
};
|
||||
_bgaMeasurePanel.Show();
|
||||
}
|
||||
|
||||
private Window _bubbleMeasurePanel;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<Window
|
||||
x:Class="XplorePlane.Views.ImageProcessing.BgaMeasurePanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="BGA空隙测量"
|
||||
Width="240" Height="260"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Topmost="True"
|
||||
ShowInTaskbar="False">
|
||||
<Window.Resources>
|
||||
<Style x:Key="ToolToggleStyle" TargetType="RadioButton">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="RadioButton">
|
||||
<Border x:Name="Bd" Background="#EEEEEE" BorderBrush="#CCCCCC"
|
||||
BorderThickness="1" CornerRadius="3" Padding="14,5" Cursor="Hand">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter TargetName="Bd" Property="Background" Value="#0078D7" />
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="#005A9E" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Bd" Property="Background" Value="#DDDDDD" />
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
<Condition Property="IsChecked" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="Bd" Property="Background" Value="#006CBE" />
|
||||
</MultiTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<StackPanel Margin="10">
|
||||
<!-- 绘制模式 -->
|
||||
<TextBlock Text="绘制模式" FontWeight="SemiBold" Margin="0,0,0,4" />
|
||||
<WrapPanel>
|
||||
<RadioButton x:Name="RbVoid" Content="画气泡" IsChecked="True" Margin="0,0,6,4"
|
||||
Style="{StaticResource ToolToggleStyle}" />
|
||||
<RadioButton x:Name="RbBall" Content="画焊球" Margin="0,0,0,4"
|
||||
Style="{StaticResource ToolToggleStyle}" />
|
||||
</WrapPanel>
|
||||
<TextBlock Text="左键点两次画圆(圆心+半径),右键删除" FontSize="10" Foreground="Gray" Margin="0,2,0,0" />
|
||||
|
||||
<Separator Margin="0,8" />
|
||||
|
||||
<!-- VoidLimit -->
|
||||
<TextBlock Text="VoidLimit(%)" Margin="0,0,0,4" />
|
||||
<DockPanel>
|
||||
<TextBox x:Name="TbVoidLimit" DockPanel.Dock="Right" Width="50" Text="25.0"
|
||||
VerticalContentAlignment="Center" Margin="6,0,0,0" />
|
||||
<Slider x:Name="SliderVoidLimit" Minimum="0" Maximum="100" Value="25"
|
||||
VerticalAlignment="Center" />
|
||||
</DockPanel>
|
||||
|
||||
<Separator Margin="0,8" />
|
||||
|
||||
<!-- 结果 -->
|
||||
<TextBlock x:Name="TbResult" Text="空隙率: --" FontSize="14" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||
|
||||
<!-- 操作 -->
|
||||
<WrapPanel HorizontalAlignment="Center">
|
||||
<Button Content="完成" Padding="14,4" Click="Finish_Click" />
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Windows;
|
||||
using XP.ImageProcessing.RoiControl.Controls;
|
||||
|
||||
namespace XplorePlane.Views.ImageProcessing
|
||||
{
|
||||
public partial class BgaMeasurePanel : Window
|
||||
{
|
||||
private PolygonRoiCanvas _canvas;
|
||||
|
||||
public BgaMeasurePanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mainWin = Owner as MainWindow;
|
||||
if (mainWin != null)
|
||||
_canvas = FindChild<PolygonRoiCanvas>(mainWin);
|
||||
}
|
||||
catch { }
|
||||
|
||||
// 模式切换:通知 canvas 切换气泡/焊球
|
||||
RbVoid.Checked += (s, ev) =>
|
||||
{
|
||||
if (_canvas != null) _canvas.SetBgaDrawBall(false);
|
||||
};
|
||||
RbBall.Checked += (s, ev) =>
|
||||
{
|
||||
if (_canvas != null) _canvas.SetBgaDrawBall(true);
|
||||
};
|
||||
|
||||
// VoidLimit 同步
|
||||
SliderVoidLimit.ValueChanged += (s, ev) =>
|
||||
{
|
||||
TbVoidLimit.Text = SliderVoidLimit.Value.ToString("F1");
|
||||
_canvas?.SetBgaVoidLimit(SliderVoidLimit.Value);
|
||||
};
|
||||
|
||||
// 监听测量完成事件更新结果
|
||||
if (_canvas != null)
|
||||
{
|
||||
_canvas.MeasureCompleted += (s, ev) =>
|
||||
{
|
||||
if (ev is MeasureCompletedEventArgs args && args.MeasureType == "BgaVoid")
|
||||
{
|
||||
TbResult.Text = $"空隙率: {args.Distance:F1}%";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void Finish_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private static T FindChild<T>(DependencyObject parent) where T : DependencyObject
|
||||
{
|
||||
int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var child = System.Windows.Media.VisualTreeHelper.GetChild(parent, i);
|
||||
if (child is T t) return t;
|
||||
var result = FindChild<T>(child);
|
||||
if (result != null) return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user