TURBO-569:去掉导航相机的控制按钮,改为相机如果存在自动连接自动显示实时影像
This commit is contained in:
+45
-7
@@ -13,6 +13,7 @@ using XP.Camera;
|
|||||||
using XP.Common.Configs;
|
using XP.Common.Configs;
|
||||||
using XP.Common.Database.Implementations;
|
using XP.Common.Database.Implementations;
|
||||||
using XP.Common.Database.Interfaces;
|
using XP.Common.Database.Interfaces;
|
||||||
|
using XP.Common.GeneralForm.Views;
|
||||||
using XP.Common.Dump.Configs;
|
using XP.Common.Dump.Configs;
|
||||||
using XP.Common.Dump.Implementations;
|
using XP.Common.Dump.Implementations;
|
||||||
using XP.Common.Dump.Interfaces;
|
using XP.Common.Dump.Interfaces;
|
||||||
@@ -149,7 +150,7 @@ namespace XplorePlane
|
|||||||
Log.Error(ex, "射线源资源释放失败");
|
Log.Error(ex, "射线源资源释放失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放相机服务资源
|
// 释放导航相机服务资源
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var bootstrapper = AppBootstrapper.Instance;
|
var bootstrapper = AppBootstrapper.Instance;
|
||||||
@@ -157,12 +158,12 @@ namespace XplorePlane
|
|||||||
{
|
{
|
||||||
var cameraService = bootstrapper.Container.Resolve<ICameraService>();
|
var cameraService = bootstrapper.Container.Resolve<ICameraService>();
|
||||||
cameraService?.Dispose();
|
cameraService?.Dispose();
|
||||||
Log.Information("相机服务资源已释放");
|
Log.Information("导航相机服务资源已释放");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error(ex, "相机服务资源释放失败");
|
Log.Error(ex, "导航相机服务资源释放失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放SQLite数据库资源 | Release SQLite database resources
|
// 释放SQLite数据库资源 | Release SQLite database resources
|
||||||
@@ -234,18 +235,55 @@ namespace XplorePlane
|
|||||||
protected override Window CreateShell()
|
protected override Window CreateShell()
|
||||||
{
|
{
|
||||||
// 提前初始化模块,确保硬件服务在 MainWindow XAML 解析前已注册
|
// 提前初始化模块,确保硬件服务在 MainWindow XAML 解析前已注册
|
||||||
// 默认 Prism 顺序是 CreateShell → InitializeModules,
|
|
||||||
// 但 MainWindow 中嵌入的硬件控件会在 XAML 解析时触发 ViewModelLocator,
|
|
||||||
// 此时模块尚未加载,导致依赖解析失败
|
|
||||||
if (!_modulesInitialized)
|
if (!_modulesInitialized)
|
||||||
{
|
{
|
||||||
base.InitializeModules();
|
base.InitializeModules();
|
||||||
_modulesInitialized = true;
|
_modulesInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在主窗口显示前完成导航相机连接,避免窗口弹出后再检索导致卡顿
|
||||||
|
TryConnectCamera();
|
||||||
|
|
||||||
return Container.Resolve<MainWindow>();
|
return Container.Resolve<MainWindow>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在独立 MTA 线程中检索并连接导航相机,带 10 秒超时。
|
||||||
|
/// 连接成功后 NavigationPropertyPanelViewModel 构造时拿到的就是已连接的导航相机。
|
||||||
|
/// </summary>
|
||||||
|
private void TryConnectCamera()
|
||||||
|
{
|
||||||
|
var camera = Container.Resolve<ICameraController>();
|
||||||
|
CameraInfo? info = null;
|
||||||
|
Exception? error = null;
|
||||||
|
|
||||||
|
var thread = new System.Threading.Thread(() =>
|
||||||
|
{
|
||||||
|
try { info = camera.Open(); }
|
||||||
|
catch (Exception ex) { error = ex; }
|
||||||
|
});
|
||||||
|
thread.IsBackground = true;
|
||||||
|
thread.SetApartmentState(System.Threading.ApartmentState.MTA);
|
||||||
|
thread.Start();
|
||||||
|
|
||||||
|
bool completed = thread.Join(TimeSpan.FromSeconds(10));
|
||||||
|
|
||||||
|
if (!completed)
|
||||||
|
{
|
||||||
|
Log.Warning("导航相机检索超时 (10s),跳过自动连接");
|
||||||
|
HexMessageBox.Show("导航相机检索超时(10秒),请检查导航相机连接后重启软件。", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
else if (error != null)
|
||||||
|
{
|
||||||
|
Log.Warning(error, "导航相机自动连接失败: {Message}", error.Message);
|
||||||
|
HexMessageBox.Show($"导航相机连接失败: {error.Message}", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Information("导航相机已连接: {ModelName} (SN: {SerialNumber})", info!.ModelName, info.SerialNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模块已在 CreateShell 中提前初始化,此处跳过避免重复加载
|
/// 模块已在 CreateShell 中提前初始化,此处跳过避免重复加载
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -327,7 +365,7 @@ namespace XplorePlane
|
|||||||
containerRegistry.RegisterForNavigation<CncPageView>();
|
containerRegistry.RegisterForNavigation<CncPageView>();
|
||||||
containerRegistry.RegisterForNavigation<MatrixPageView>();
|
containerRegistry.RegisterForNavigation<MatrixPageView>();
|
||||||
|
|
||||||
// ── 相机服务(单例)──
|
// ── 导航相机服务(单例)──
|
||||||
containerRegistry.RegisterSingleton<ICameraFactory, CameraFactory>();
|
containerRegistry.RegisterSingleton<ICameraFactory, CameraFactory>();
|
||||||
containerRegistry.RegisterSingleton<ICameraController>(() =>
|
containerRegistry.RegisterSingleton<ICameraController>(() =>
|
||||||
new CameraFactory().CreateController("Basler"));
|
new CameraFactory().CreateController("Basler"));
|
||||||
|
|||||||
@@ -176,6 +176,24 @@ namespace XplorePlane.ViewModels
|
|||||||
ApplyPixelFormatCommand = new DelegateCommand(() => ApplyCameraParam(() => _camera.SetPixelFormat(SelectedPixelFormat)), () => IsCameraConnected);
|
ApplyPixelFormatCommand = new DelegateCommand(() => ApplyCameraParam(() => _camera.SetPixelFormat(SelectedPixelFormat)), () => IsCameraConnected);
|
||||||
RefreshCameraParamsCommand = new DelegateCommand(RefreshCameraParams, () => IsCameraConnected);
|
RefreshCameraParamsCommand = new DelegateCommand(RefreshCameraParams, () => IsCameraConnected);
|
||||||
OpenCameraSettingsCommand = new DelegateCommand(OpenCameraSettings, () => IsCameraConnected);
|
OpenCameraSettingsCommand = new DelegateCommand(OpenCameraSettings, () => IsCameraConnected);
|
||||||
|
|
||||||
|
// 相机已在 App 启动阶段连接,直接检测状态并启动实时预览
|
||||||
|
if (_camera.IsConnected)
|
||||||
|
{
|
||||||
|
_camera.ImageGrabbed += OnCameraImageGrabbed;
|
||||||
|
_camera.GrabError += OnCameraGrabError;
|
||||||
|
_camera.ConnectionLost += OnCameraConnectionLost;
|
||||||
|
|
||||||
|
IsCameraConnected = true;
|
||||||
|
CameraStatusText = "已连接";
|
||||||
|
RefreshCameraParams();
|
||||||
|
StartGrab();
|
||||||
|
IsLiveViewEnabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CameraStatusText = "未检测到相机";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Camera Methods
|
#region Camera Methods
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- 标题栏 -->
|
<!-- 标题栏 -->
|
||||||
@@ -56,50 +55,5 @@
|
|||||||
<Run Foreground="#0078D4" Text="{Binding CameraPixelCoord, Mode=OneWay}" />
|
<Run Foreground="#0078D4" Text="{Binding CameraPixelCoord, Mode=OneWay}" />
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- 控制按钮栏 -->
|
|
||||||
<Border
|
|
||||||
Grid.Row="3"
|
|
||||||
Background="#F0F0F0"
|
|
||||||
BorderBrush="#DDDDDD"
|
|
||||||
BorderThickness="0,1,0,0"
|
|
||||||
Padding="4">
|
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
|
||||||
<Button
|
|
||||||
Command="{Binding ConnectCameraCommand}"
|
|
||||||
Width="60" Height="26"
|
|
||||||
Margin="2"
|
|
||||||
Background="#4CAF50"
|
|
||||||
Foreground="#000000"
|
|
||||||
Content="连接" />
|
|
||||||
<Button
|
|
||||||
Command="{Binding DisconnectCameraCommand}"
|
|
||||||
Width="60" Height="26"
|
|
||||||
Margin="2"
|
|
||||||
Background="#F44336"
|
|
||||||
Foreground="#000000"
|
|
||||||
Content="断开" />
|
|
||||||
<Button
|
|
||||||
Command="{Binding StartGrabCommand}"
|
|
||||||
Width="60" Height="26"
|
|
||||||
Margin="2"
|
|
||||||
Background="#2196F3"
|
|
||||||
Foreground="#000000"
|
|
||||||
Content="采集" />
|
|
||||||
<Button
|
|
||||||
Command="{Binding StopGrabCommand}"
|
|
||||||
Width="60" Height="26"
|
|
||||||
Margin="2"
|
|
||||||
Background="#FF9800"
|
|
||||||
Foreground="#000000"
|
|
||||||
Content="停止" />
|
|
||||||
<CheckBox
|
|
||||||
IsChecked="{Binding IsLiveViewEnabled}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Margin="6,0,0,0"
|
|
||||||
Foreground="#333333"
|
|
||||||
Content="实时" />
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@@ -28,8 +28,16 @@ namespace XplorePlane.Views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 双击相机图像时,计算并显示点击位置的像素坐标。
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// TODO: 后续需要将点击的像素坐标通过 CalibrationProcessor 转换为世界坐标,
|
||||||
|
/// 再传给运动机构执行定位。
|
||||||
|
/// </remarks>
|
||||||
private void ImgCamera_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
private void ImgCamera_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (e.ClickCount != 2) return;
|
||||||
if (_viewModel?.CameraImageSource == null) return;
|
if (_viewModel?.CameraImageSource == null) return;
|
||||||
|
|
||||||
var image = (Image)sender;
|
var image = (Image)sender;
|
||||||
|
|||||||
Reference in New Issue
Block a user