fix(plot): 默认线宽 1.0px、菜单文本左对齐、散点白边修复与大文件拖拽性能优化
1) 默认线宽改为 1.0px - SignalStyle::lineWidth 初值 1.6f -> 1.0f (DataModel.hpp / DataModel.cpp) - 新增 LaneScroll() const 重载,供 const 的 MakeSceneCacheKey() 读取 2) 网格右键菜单文本左对齐 - PopupMenu 的 HEADER / NORMAL / EDIT 三类条目统一使用 kMarkerColumn(22.0f) 作为文本列,替换原先写死的 8.0f,使 "网格 N"、"Y 轴最大值"、 "Y 轴最小值"、"选区 Y 轴自适应" 等所有条目左边缘严格对齐 3) 修复散点/点线模式下数据点重叠处的白色缝隙 - 根因: GDI+ GraphicsPath 默认 FillModeAlternate(奇偶填充),重叠圆的交叠区域 被反向填充,视觉上表现为白色缺口/白边 - 主绘制与拖拽 ghost 的 GraphicsPath 均显式 SetFillMode(FillModeWinding) - ghost 由逐点 FillEllipse 改为单个 GraphicsPath 一次 FillPath(批量绘制) 4) 大文件拖拽流畅性优化 (VERY_BIG_DATA.CSV 1.77GB / 5 信号) - 新增拖拽静态场景缓存: 在 MOVE_SIGNAL / CURSOR_MOVE 期间把整个客户区 (绘图区 + 标签页 + 工具栏 + 信号面板) 捕快到 m_sceneDc 位图,后续帧直接 BitBlt,仅在 SceneCacheKey(dragMode/viewMin/viewMax/laneScroll/laneCount/ 区域/scale) 变化时重绘。Application::Render 在复用场景时跳过窗口背景与 各子控件绘制,缓存位图由 ~PlotView() 释放 - 失效点: SetContext / SetScale / Layout / InvalidatePolylineCache - 光标数值读数从 PaintLane 抽出为 PaintLaneReadouts(),在缓存 blit 之后绘制, 避免读数被缓存导致拖动时显示旧值 - 拖拽 ghost 复用已有 PolylineCacheEntry,改用 TranslateTransform 偏移, 不再重复构造折线顶点 - 实测: 拖拽帧耗时 134-146ms -> 22-25ms;散点模式拖拽约 24.6ms; 非拖拽重绘维持约 118ms;空闲 CPU 0.00% 构建: make clean; make all 无警告无错误
This commit is contained in:
1 parent
04e98ee041
commit
a3e638fa58
6 files changed
+407
-29
No files matched your search
@@ -66,6 +66,11 @@ namespace jdi
|
||||
public:
|
||||
PlotView();
|
||||
|
||||
/**
|
||||
* @brief 析构:释放拖拽静态场景缓存的离屏位图。
|
||||
*/
|
||||
~PlotView();
|
||||
|
||||
/**
|
||||
* @brief 设置宿主窗口句柄(用于剪贴板所有者)。
|
||||
* @param [IN] host 宿主窗口句柄,允许为空。
|
||||
@@ -247,6 +252,16 @@ namespace jdi
|
||||
*/
|
||||
bool CancelDrag();
|
||||
|
||||
/**
|
||||
* @brief 判断本帧是否可以整体复用拖拽静态场景缓存。
|
||||
*
|
||||
* 拖动信号曲线 / 时间光标时视图与数据都不变,缓存内容仍然有效。
|
||||
* 宿王可据此跳过工具栏/标签栏/面板的重复绘制(它们也在缓存内)。
|
||||
*
|
||||
* @return 可复用返回 true。
|
||||
*/
|
||||
bool CanReuseSceneCache() const;
|
||||
|
||||
/**
|
||||
* @brief 退出全部缩放模式(时间轴缩放 / Y 轴缩放),使工具栏缩放按钮回到未选中态。
|
||||
* @return 之前处于某个缩放模式返回 true。
|
||||
@@ -722,6 +737,15 @@ namespace jdi
|
||||
*/
|
||||
void PaintEmptyState(gd::Graphics& g);
|
||||
|
||||
/**
|
||||
* @brief 绘制全部网格的时间光标读数框。
|
||||
*
|
||||
* 读数随时间光标实时变化,因此不能进入拖拽静态场景缓存,必须每帧单独绘制。
|
||||
*
|
||||
* @param [IN,OUT] g 绘图上下文。
|
||||
*/
|
||||
void PaintLaneReadouts(gd::Graphics& g);
|
||||
|
||||
const UiFonts* m_fonts = nullptr; /**< 字体资源。 */
|
||||
const Theme* m_theme = nullptr; /**< 主题资源。 */
|
||||
const DataSet* m_dataSet = nullptr; /**< 数据集合(只读访问)。 */
|
||||
@@ -819,6 +843,74 @@ namespace jdi
|
||||
|
||||
mutable std::deque<PolylineCacheEntry> m_polylineCache; /**< 折线顶点缓存(按几何键复用)。 */
|
||||
|
||||
/**
|
||||
* @brief 静态场景缓存的几何键。
|
||||
*
|
||||
* 只要这组参数完全一致,"背景 + 全部网格 + 时间轴"的渲染结果就逐像素相同,
|
||||
* 可以直接复用离屏位图,无需重算百万级采样的包络与绘制。
|
||||
*/
|
||||
struct SceneCacheKey
|
||||
{
|
||||
int dragMode = -1; /**< 拖拽模式(拖拽中才允许复用)。 */
|
||||
double viewMin = 0.0; /**< 时间轴下界。 */
|
||||
double viewMax = 0.0; /**< 时间轴上界。 */
|
||||
float laneScroll = 0.0f; /**< 网格滚动偏移。 */
|
||||
int laneCount = 0; /**< 网格数量。 */
|
||||
float areaX = 0.0f; /**< 绘图区左上角。 */
|
||||
float areaY = 0.0f;
|
||||
float areaW = 0.0f; /**< 绘图区尺寸。 */
|
||||
float areaH = 0.0f;
|
||||
float scale = 1.0f; /**< DPI 缩放。 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 构造当前场景的缓存键。
|
||||
* @return 缓存键。
|
||||
*/
|
||||
SceneCacheKey MakeSceneCacheKey() const;
|
||||
|
||||
/**
|
||||
* @brief 确保离屏缓存位图存在且尺寸匹配。
|
||||
* @param [IN] width 位图宽度(像素)。
|
||||
* @param [IN] height 位图高度(像素)。
|
||||
* @return 可用返回 true。
|
||||
*/
|
||||
bool EnsureSceneCache(int width, int height);
|
||||
|
||||
/**
|
||||
* @brief 把当前画布内容(背景 + 界面外框 + 全部网格 + 时间轴)拷贝进离屏缓存。
|
||||
* @param [IN,OUT] g 当前绘图上下文(必须未设置裁剪区)。
|
||||
* @return 拷贝成功返回 true。
|
||||
*/
|
||||
bool CaptureSceneCache(gd::Graphics& g);
|
||||
|
||||
/**
|
||||
* @brief 把离屏缓存贴回画布。
|
||||
* @param [IN,OUT] g 绘图上下文。
|
||||
* @return 命中缓存并贴图成功返回 true。
|
||||
*/
|
||||
bool BlitSceneCache(gd::Graphics& g);
|
||||
|
||||
/**
|
||||
* @brief 丢弃缓存标记(下次绘制会重新捕获)。
|
||||
*/
|
||||
void InvalidateSceneCache();
|
||||
|
||||
/**
|
||||
* @brief 释放离屏缓存占用的 GDI 对象。
|
||||
*/
|
||||
void ReleaseSceneCache();
|
||||
|
||||
HBITMAP m_sceneBitmap = nullptr; /**< 离屏缓存位图。 */
|
||||
HDC m_sceneDc = nullptr; /**< 离屏缓存设备上下文。 */
|
||||
HGDIOBJ m_sceneOldBitmap = nullptr; /**< 离屏 DC 原选位图。 */
|
||||
int m_sceneWidth = 0; /**< 离屏位图宽度。 */
|
||||
int m_sceneHeight = 0; /**< 离屏位图高度。 */
|
||||
int m_sceneX = 0; /**< 离屏缓存对应的客户区横坐标。 */
|
||||
int m_sceneY = 0; /**< 离屏缓存对应的客户区纵坐标。 */
|
||||
bool m_sceneValid = false; /**< 缓存内容是否有效。 */
|
||||
SceneCacheKey m_sceneKey; /**< 缓存对应的场景参数。 */
|
||||
|
||||
/**
|
||||
* @brief 查询坐标命中的图例条目。
|
||||
* @param [IN] x 客户区横坐标。
|
||||
|
||||
Reference in new issue
Block a user