十字辅助线
This commit is contained in:
@@ -1878,7 +1878,10 @@
|
||||
"Telerik.UI.for.Wpf.NetCore.Xaml": "2024.1.408"
|
||||
},
|
||||
"runtime": {
|
||||
"XP.Common.dll": {}
|
||||
"XP.Common.dll": {
|
||||
"assemblyVersion": "1.4.16.1",
|
||||
"fileVersion": "1.4.16.1"
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"en-US/XP.Common.resources.dll": {
|
||||
|
||||
@@ -18,4 +18,9 @@ namespace XplorePlane.Events
|
||||
/// 测量工具激活事件,由 MainViewModel 发布,ViewportPanelViewModel 订阅
|
||||
/// </summary>
|
||||
public class MeasurementToolEvent : PubSubEvent<MeasurementToolMode> { }
|
||||
|
||||
/// <summary>
|
||||
/// 十字辅助线切换事件
|
||||
/// </summary>
|
||||
public class ToggleCrosshairEvent : PubSubEvent { }
|
||||
}
|
||||
|
||||
@@ -81,6 +81,9 @@ namespace XplorePlane.ViewModels
|
||||
public DelegateCommand AngleMeasureCommand { get; }
|
||||
public DelegateCommand ThroughHoleFillRateMeasureCommand { get; }
|
||||
|
||||
// 辅助线命令
|
||||
public DelegateCommand ToggleCrosshairCommand { get; }
|
||||
|
||||
// 设置命令
|
||||
public DelegateCommand OpenLanguageSwitcherCommand { get; }
|
||||
public DelegateCommand OpenRealTimeLogViewerCommand { get; }
|
||||
@@ -164,6 +167,10 @@ namespace XplorePlane.ViewModels
|
||||
AngleMeasureCommand = new DelegateCommand(ExecuteAngleMeasure);
|
||||
ThroughHoleFillRateMeasureCommand = new DelegateCommand(ExecuteThroughHoleFillRateMeasure);
|
||||
|
||||
// 辅助线命令
|
||||
ToggleCrosshairCommand = new DelegateCommand(() =>
|
||||
_eventAggregator.GetEvent<ToggleCrosshairEvent>().Publish());
|
||||
|
||||
// 硬件命令
|
||||
AxisResetCommand = new DelegateCommand(ExecuteAxisReset);
|
||||
OpenDetectorConfigCommand = new DelegateCommand(ExecuteOpenDetectorConfig);
|
||||
|
||||
@@ -154,6 +154,10 @@ namespace XplorePlane.ViewModels
|
||||
// 订阅测量工具事件
|
||||
eventAggregator.GetEvent<MeasurementToolEvent>()
|
||||
.Subscribe(OnMeasurementToolActivated, ThreadOption.UIThread);
|
||||
|
||||
// 订阅十字辅助线切换事件
|
||||
eventAggregator.GetEvent<ToggleCrosshairEvent>()
|
||||
.Subscribe(OnToggleCrosshair, ThreadOption.UIThread);
|
||||
}
|
||||
|
||||
private void OnMeasurementToolActivated(MeasurementToolMode mode)
|
||||
@@ -162,6 +166,23 @@ namespace XplorePlane.ViewModels
|
||||
_logger?.Info("测量工具模式切换: {Mode}", mode);
|
||||
}
|
||||
|
||||
#region 十字辅助线
|
||||
|
||||
private bool _showCrosshair;
|
||||
public bool ShowCrosshair
|
||||
{
|
||||
get => _showCrosshair;
|
||||
set => SetProperty(ref _showCrosshair, value);
|
||||
}
|
||||
|
||||
private void OnToggleCrosshair()
|
||||
{
|
||||
ShowCrosshair = !ShowCrosshair;
|
||||
_logger?.Info("十字辅助线: {State}", ShowCrosshair ? "显示" : "隐藏");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnImageCaptured(ImageCapturedEventArgs args)
|
||||
{
|
||||
if (args?.ImageData == null || args.Width == 0 || args.Height == 0) return;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace XplorePlane.Views
|
||||
{
|
||||
/// <summary>返回输入值的一半,用于十字线居中定位</summary>
|
||||
public class HalfValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> value is double d ? d / 2.0 : 0.0;
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -146,6 +146,7 @@
|
||||
<StackPanel>
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Title="中心十字线"
|
||||
Command="{Binding ToggleCrosshairCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/crosshair.png"
|
||||
Text="辅助线" />
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:roi="clr-namespace:XP.ImageProcessing.RoiControl.Controls;assembly=XP.ImageProcessing.RoiControl"
|
||||
xmlns:local="clr-namespace:XplorePlane.Views"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
d:DesignHeight="400"
|
||||
d:DesignWidth="600"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
|
||||
<local:HalfValueConverter x:Key="HalfConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid Background="#FFFFFF">
|
||||
<Grid.RowDefinitions>
|
||||
@@ -55,6 +57,8 @@
|
||||
</ContextMenu>
|
||||
</roi:PolygonRoiCanvas.ContextMenu>
|
||||
</roi:PolygonRoiCanvas>
|
||||
|
||||
<!-- 十字辅助线通过代码绘制到 mainCanvas 内部,跟随图像缩放平移 -->
|
||||
</Grid>
|
||||
|
||||
<!-- 图像信息栏 -->
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using Microsoft.Win32;
|
||||
using XP.ImageProcessing.RoiControl.Controls;
|
||||
using Prism.Ioc;
|
||||
using XplorePlane.Events;
|
||||
using XplorePlane.ViewModels;
|
||||
|
||||
@@ -65,10 +66,25 @@ namespace XplorePlane.Views
|
||||
if (e is CanvasClickedEventArgs args)
|
||||
OnCanvasClicked(args.Position);
|
||||
};
|
||||
|
||||
// 直接订阅 Prism 事件,不依赖 DataContext 的 PropertyChanged
|
||||
try
|
||||
{
|
||||
var ea = Prism.Ioc.ContainerLocator.Current?.Resolve<Prism.Events.IEventAggregator>();
|
||||
ea?.GetEvent<ToggleCrosshairEvent>().Subscribe(() =>
|
||||
{
|
||||
_crosshairVisible = !_crosshairVisible;
|
||||
ToggleCrosshairOnCanvas(_crosshairVisible);
|
||||
}, Prism.Events.ThreadOption.UIThread);
|
||||
}
|
||||
catch { /* 设计时或容器未初始化时忽略 */ }
|
||||
}
|
||||
|
||||
private bool _crosshairVisible;
|
||||
|
||||
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[VP] DataContextChanged: old={e.OldValue?.GetType().Name}, new={e.NewValue?.GetType().Name}");
|
||||
if (e.OldValue is INotifyPropertyChanged oldVm)
|
||||
oldVm.PropertyChanged -= OnVmPropertyChanged;
|
||||
if (e.NewValue is INotifyPropertyChanged newVm)
|
||||
@@ -78,6 +94,7 @@ namespace XplorePlane.Views
|
||||
private void OnVmPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (sender is not ViewportPanelViewModel vm) return;
|
||||
System.Diagnostics.Debug.WriteLine($"[VP] PropertyChanged: {e.PropertyName}");
|
||||
if (e.PropertyName == nameof(ViewportPanelViewModel.CurrentMeasurementMode))
|
||||
{
|
||||
if (vm.CurrentMeasurementMode != MeasurementToolMode.None)
|
||||
@@ -86,6 +103,10 @@ namespace XplorePlane.Views
|
||||
else
|
||||
RemoveOverlay();
|
||||
}
|
||||
else if (e.PropertyName == nameof(ViewportPanelViewModel.ShowCrosshair))
|
||||
{
|
||||
// 十字线通过直接订阅 ToggleCrosshairEvent 处理
|
||||
}
|
||||
}
|
||||
|
||||
#region 覆盖层管理
|
||||
@@ -324,6 +345,47 @@ namespace XplorePlane.Views
|
||||
return null;
|
||||
}
|
||||
|
||||
private void UpdateCrosshairLines()
|
||||
{
|
||||
// 十字线位置通过 XAML 绑定自动计算
|
||||
}
|
||||
|
||||
private Line _crosshairH, _crosshairV;
|
||||
|
||||
private void ToggleCrosshairOnCanvas(bool show)
|
||||
{
|
||||
var mainCanvas = FindChildByName<Canvas>(RoiCanvas, "mainCanvas");
|
||||
System.Diagnostics.Debug.WriteLine($"[VP] ToggleCrosshair show={show}, mainCanvas={mainCanvas != null}, W={RoiCanvas.CanvasWidth}, H={RoiCanvas.CanvasHeight}");
|
||||
if (mainCanvas == null) return;
|
||||
|
||||
if (show)
|
||||
{
|
||||
double w = RoiCanvas.CanvasWidth;
|
||||
double h = RoiCanvas.CanvasHeight;
|
||||
if (w <= 0 || h <= 0) return;
|
||||
|
||||
_crosshairH = new Line
|
||||
{
|
||||
X1 = 0, Y1 = h / 2, X2 = w, Y2 = h / 2,
|
||||
Stroke = Brushes.Red, StrokeThickness = 1, Opacity = 0.7,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
_crosshairV = new Line
|
||||
{
|
||||
X1 = w / 2, Y1 = 0, X2 = w / 2, Y2 = h,
|
||||
Stroke = Brushes.Red, StrokeThickness = 1, Opacity = 0.7,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
mainCanvas.Children.Add(_crosshairH);
|
||||
mainCanvas.Children.Add(_crosshairV);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_crosshairH != null) { mainCanvas.Children.Remove(_crosshairH); _crosshairH = null; }
|
||||
if (_crosshairV != null) { mainCanvas.Children.Remove(_crosshairV); _crosshairV = null; }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 右键菜单
|
||||
|
||||
Reference in New Issue
Block a user