修复Toprie热像仪实时温度信息显示问题,调整UpdateImageOnUI方法实现和UpdateRealTimeInfoOnUI方法语法错误

This commit is contained in:
zqm
2025-11-05 14:25:24 +08:00
parent 4b319fa15b
commit aace6d78f7
2 changed files with 151 additions and 145 deletions

View File

@@ -31,6 +31,10 @@ namespace JoyD.Windows.CS.Toprie
// 信息图像,用于显示额外信息 // 信息图像,用于显示额外信息
private Image _infoImage = null; private Image _infoImage = null;
// 实时信息图像,用于显示温度等实时数据
private Image _displayImage = null;
private readonly object _displayImageLock = new object();
// 最近一次获取到的温度数据 // 最近一次获取到的温度数据
// 温度显示状态标志 // 温度显示状态标志
@@ -390,6 +394,17 @@ namespace JoyD.Windows.CS.Toprie
Console.WriteLine("InfoImage已初始化为透明bitmap"); Console.WriteLine("InfoImage已初始化为透明bitmap");
} }
// 初始化DisplayImage为透明bitmap
lock (_displayImageLock)
{
_displayImage = new Bitmap(BUFFER_WIDTH, BUFFER_HEIGHT);
using (Graphics g = Graphics.FromImage(_displayImage))
{
g.Clear(Color.Transparent);
}
Console.WriteLine("DisplayImage已初始化为透明bitmap");
}
// 初始化图像框的bitmap为透明 // 初始化图像框的bitmap为透明
if (imageBox != null && !imageBox.IsDisposed) if (imageBox != null && !imageBox.IsDisposed)
{ {
@@ -771,50 +786,17 @@ namespace JoyD.Windows.CS.Toprie
} }
} }
// 步骤3在就绪条件下如果有温度数据时间在最近3秒内显示最高温度居中显示 // 步骤2.1绘制DisplayImage实时温度信息等
if (!_isPaused && IsDevicePingable && _deviceManager != null && _deviceManager.ConnectionStatus == ConnectionStatus.Connected) lock (_displayImageLock)
{ {
TemperatureData temperatureData = _deviceManager.LastTemperature; if (_displayImage != null)
if (temperatureData != null && temperatureData.Timestamp != null)
{ {
// 检查温度数据时间是否在最近3秒内 g.DrawImage(_displayImage, 0, 0);
TimeSpan timeDiff = DateTime.Now - temperatureData.Timestamp; }
if (timeDiff.TotalSeconds <= 3)
{
// 有有效温度数据,居中显示最高温度
string tempText = $"最高温度: {temperatureData.MaxTemperature:F2} °C";
Color textColor = Color.White;
using (Font font = new Font("Arial", 24, FontStyle.Bold))
using (SolidBrush textBrush = new SolidBrush(textColor))
{
StringFormat format = new StringFormat() {
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
// 计算文本位置,确保居中显示
RectangleF textRect = new RectangleF(0, 0, BUFFER_WIDTH, BUFFER_HEIGHT);
// 添加半透明背景以提高可读性
SizeF textSize = g.MeasureString(tempText, font);
RectangleF bgRect = new RectangleF(
(BUFFER_WIDTH - textSize.Width - 20) / 2,
(BUFFER_HEIGHT - textSize.Height - 20) / 2,
textSize.Width + 20,
textSize.Height + 20
);
using (SolidBrush bgBrush = new SolidBrush(Color.FromArgb(128, 0, 0, 0)))
{
g.FillRectangle(bgBrush, bgRect);
} }
// 居中绘制温度信息 // 注意:温度信息不再直接在这里绘制
g.DrawString(tempText, font, textBrush, textRect, format); // 而是在UpdateRealTimeInfoOnUI方法中绘制到_displayImage然后在这里绘制到_imageBuffer
}
}
}
}
} }
// 在同一个锁内创建缓冲区的副本,避免重复锁定 // 在同一个锁内创建缓冲区的副本,避免重复锁定
@@ -1771,6 +1753,24 @@ namespace JoyD.Windows.CS.Toprie
} }
} }
// 释放DisplayImage资源
lock (_displayImageLock)
{
if (_displayImage != null)
{
try
{
_displayImage.Dispose();
_displayImage = null;
Console.WriteLine("DisplayImage资源已释放");
}
catch (Exception ex)
{
Console.WriteLine($"清理DisplayImage资源异常: {ex.Message}");
}
}
}
// 释放组件资源 // 释放组件资源
if (components != null) if (components != null)
{ {
@@ -1853,12 +1853,14 @@ namespace JoyD.Windows.CS.Toprie
/// </summary> /// </summary>
private void UpdateRealTimeInfoOnUI() private void UpdateRealTimeInfoOnUI()
{ {
// 1. 以透明色清空图像缓冲区的温度显示区域 lock (_displayImageLock)
{
// 1. 以透明色清空DisplayImage
// 遵循README要求中途不进行Dispose和设置为null只在上面进行绘制 // 遵循README要求中途不进行Dispose和设置为null只在上面进行绘制
if (_imageBuffer == null) if (_displayImage == null)
return; return;
using (Graphics g = Graphics.FromImage(_imageBuffer)) using (Graphics g = Graphics.FromImage(_displayImage))
{ {
// 清除DisplayImage为透明色 // 清除DisplayImage为透明色
g.Clear(Color.Transparent); g.Clear(Color.Transparent);
@@ -1938,8 +1940,8 @@ namespace JoyD.Windows.CS.Toprie
if (isGlobalTemperatureMode) if (isGlobalTemperatureMode)
{ {
// 计算文本区域的位置(整体居中) // 计算文本区域的位置(整体居中)
float textAreaX = (_imageBuffer.Width - maxTextWidth) / 2; float textAreaX = (_displayImage.Width - maxTextWidth) / 2;
float textAreaY = (_imageBuffer.Height - totalTextHeight) / 2; float textAreaY = (_displayImage.Height - totalTextHeight) / 2;
// 绘制温度文本 // 绘制温度文本
float currentY = textAreaY; float currentY = textAreaY;
@@ -1954,8 +1956,8 @@ namespace JoyD.Windows.CS.Toprie
else if (_showAreaTemperature) else if (_showAreaTemperature)
{ {
// 计算文本区域的位置(整体居中显示) // 计算文本区域的位置(整体居中显示)
float textAreaX = (_imageBuffer.Width - maxTextWidth) / 2; float textAreaX = (_displayImage.Width - maxTextWidth) / 2;
float textAreaY = (_imageBuffer.Height - totalTextHeight) / 2; float textAreaY = (_displayImage.Height - totalTextHeight) / 2;
// 绘制温度文本 // 绘制温度文本
float currentY = textAreaY; float currentY = textAreaY;
@@ -1972,6 +1974,10 @@ namespace JoyD.Windows.CS.Toprie
format.Dispose(); format.Dispose();
} }
// 设置显示状态标志
_isDisplayingInfo = true;
}
// 标记信息正在显示 // 标记信息正在显示
_isDisplayingInfo = true; _isDisplayingInfo = true;
} }

View File

@@ -15,20 +15,20 @@
3. Ping通状态变化时修改Ping状态调用更新Info 3. Ping通状态变化时修改Ping状态调用更新Info
4. 图像更新时保存LastImage调用更新UI 4. 图像更新时保存LastImage调用更新UI
5. 2-4 只在非暂停状态下调用更新暂停状态下不更新Info和UI 5. 2-4 只在非暂停状态下调用更新暂停状态下不更新Info和UI
6. 数据显示菜单勾选变化时,调用实时显示 6. 数据显示菜单勾选变化时,调用更新实时信息
### 更新Info ### 更新Info
1. 以透明色清空Info 1. 以透明色清空Info
2. 如果暂停显示暂停信息否则如果Ping不通或断开显示重连信息否则就绪 2. 如果暂停显示暂停信息否则如果Ping不通或断开显示重连信息否则就绪
3. 如果未就绪调用更新UI,否则不调用实时显示 3. 如果未就绪调用更新UI
### 更新UI ### 更新UI
1. 先将LastImage绘制到全局缓冲 1. 先将LastImage绘制到全局缓冲
2. 再将InfoImage绘制到缓冲 2. 再将InfoImage绘制到缓冲
3. 在就绪条件下将Display绘制到缓冲 3. 在就绪条件下,调用更新实时信息,并将DisplayImage绘制到缓冲
4. 最后一次性绘制到图像框的bitmap 4. 最后一次性绘制到图像框的bitmap
### 实时显示 ### 更新实时信息
1. 以透明色清空DisplayImage 1. 以透明色清空DisplayImage
2. 如果没有温度数据或温度数据的时间3秒之前返回 2. 如果没有温度数据或温度数据的时间3秒之前返回
3. 温度显示菜单下如果未勾选区域温度和全局温度,则不显示任何温度信息 3. 温度显示菜单下如果未勾选区域温度和全局温度,则不显示任何温度信息