频谱分析仪 UI 自定义绘制
第一部分实时频谱分析自定义绘制层构造参数决定行为枚举含义ENRTSABaseTypem_basetype图形类型普通频谱 / 放大 / PvT / 概率密度(Thick) 等ENRTSAColorTypem_colortype是否显示右侧色温条Color_Y有Color_N无TraceView 与 paint 的分工模式TraceViewpaintBase_Spec/Base_SpecLine/Base_PvT等白色频谱迹线 网格参数文字、色条若开启、MarkerBase_Thick频率功率/概率密度默认 DisplayType4仅网格/坐标轴密度图 白色迹线 色条 标注 MarkerBase_Thick模式下不调用TraceView::UpdateTraceData迹线完全由paint → DrawTraceData绘制。1.2 paint 主流程七步第一步初始化绘制环境painter-save()保存画布状态。设置主题文字色、12pt 字体、文字抗锯齿。通过pixMapper-GraphRect计算绑图区及顶部/底部文字 Y 坐标。第二步语言分支Language 0英文标注否则中文。结构相同仅字符串不同。第三步按 BaseType 绘制参数文字仅文字无图形数据BaseType顶部底部Base_Spec/SpecLine/SpecLine2Y 轴刻度、参考电平中心频率、扫宽、RBW、采集时间Base_Magnify/Base_Line同上Zone 中心频率、Zone 扫宽Base_PvT—RBW、刻度、采集时间Base_ThickY 轴刻度、参考电平中心频率、扫宽、RBW、采集时间数值由SAUnits自动格式化dB、dBm、Hz、s。第四步绘制右侧色温条详见第二部分触发m_colortype Color_Y或m_basetype Base_Thick。第五步概率密度 白色迹线仅 Base_Thick色条旁写五档百分比标签100.0%、14.9%、2.2%、0.3%、0.0%。DrawPointData底层彩色密度图。DrawTraceData顶层白色瞬时谱线。绘制顺序密度底→ 迹线顶。第六步Marker 信息所有 BaseType右上角显示当前选中标记的频率/幅度或 Delta 差值频率精度随Span/SweepPoint自适应。第七步painter-restore()结束。1.3 DrawPointData — 概率密度图概率密度图是统计信号在「频率 幅度」二维平面上出现的频次 / 概率专门抓瞬态、跳变、间歇性、低占空比信号是普通频谱迹线做不到的。数据m_BitMapData256 行功率档× N 列频率档m_Scale/m_Offset将行索引映射为 dBm。步骤空数据则返回扫描矩阵求maxColor归一化。每行功率 → 像素 YGetYMaxData/GetYMinData。按屏幕宽度合并水平像素避免过密。非零单元命中比 值/maxColor→GetSelectColor(colors, 命中比)→fillRect。密度图与右侧色条共用同一colors向量保证图例与图像一致。1.4 DrawTraceData — 白色瞬时迹线数据m_TraceData长度m_TraceNum。点数 ≥ 像素宽GetCompressedData每列取 max/min画竖线段保峰。点数 像素宽GetEnlargedData扩展宽度画折线。Y 坐标经pixMapper-YValueToPixel转换画笔白色drawLines批量绘制。1.5 多类型策略总览第三步参数文字所有类型 ↓ Color_Y 或 Base_Thick ? → 第四步色温条 ↓ Base_Thick ? → 第五步密度 白线 ↓ 第六步Marker所有类型1.6 数据流Base_ReceiveData ├─ 所有模式Trace1 → m_TraceData ├─ Base_ThickBitMap → m_BitMapData设置 Scale/Offset/BitMapNum不调 UpdateTraceData └─ 其他模式UpdateTraceData SignalUpdate迹线由 TraceView 画paint只读rtasParam、markerParam不修改数据。第二部分色温系统专题色温逻辑是AllColorData()预生成paint运行时查表使用。2.1 全局状态变量静态变量默认值作用m_AllColor—6 套完整调色板QMapkey0~5m_ColorType1当前使用的方案对应ParamCode::ColorSelectm_MaxColor100色条顶部参考位置 %FeferColorLocatm_MinColor0色条底部位置 %BottomColorLocatm_MaxYData/m_MinYData0 / -100密度图 Y 轴 dBm 范围用户参数映射RtsaMainWidget::OnParamChangedColorSelect→SetColorType(index)→ 切换 6 套配色FeferColorLocat→SetFeferData→ 色条顶部裁剪BottomColorLocat→SetBottomData→ 色条底部裁剪ReferenceLevel/AxisYScale→SetYRange→ 密度图 Y 映射2.2 AllColorData — 六套调色板预生成调用时机RtsaMainWidget构造时RtsaPublicFunc::AllColorData()只执行一次。基本参数colorBarLength 1530约 255×6 级渐变tempLength 255为每段长度。方案 0 — 冷色按顺序生成 4 段 RGB 线性渐变段渐变方向视觉1B↑蓝→青(0, t, 1)2G↓青→绿(0, 1, 1-t)步长 23R↑绿→黄(t, 1, 0)步长 24G↓黄→红(1, 1-t, 0)方案 1 — 暖色6 段完整彩虹环每段 255 色段渐变1红→黄(1, t, 0)2黄→绿((2L-i)/L, 1, 0)3绿→青(0, 1, t)4青→蓝(0, 1-t, 1)5蓝→品(t, 0, 1)6品→红(1, 0, 1-t)共约 1530 色。后续AbstractColor对暖色只取前 4/6约 1020 色作为有效范围对应红→蓝主视觉去掉尾部冗余段。方案 2 — 灰色灰度从(153/255)线性降至(30/255)约 123 级。方案 3 — 雷达色两段红→黄255 色 黄→绿255 色共 510 色。方案 4 — 火热色单段红→黄(1, (255-i)/255, 0)255 色。方案 5 — 冰霜色两段浅蓝白(i,i,1)从 255→170再过渡到(i,i,(85i)/255)至 0。设计意图启动时一次性生成高分辨率色表运行时零计算开销仅做索引抽样。2.3 AbstractColor — 按绑图高度适配色表入口AbstractColor(unsigned int width)width 绑图区像素高度。第一步按m_ColorType取veccolor m_AllColor[m_ColorType]并确定有效色数pointnum暖色取count/6*4其余取全部。第二步按width与pointnum关系分支情况策略width 0直接返回完整veccolorwidth pointnum色多屏少抽取均匀跳采样每屏像素对应色表中一个颜色width pointnum色少屏多重复每个原色重复absnum或absnum1次填满高度抽取/重复使用「商 余数分配」算法前absheight行多分配 1 个色阶保证总输出长度恰好等于width。输出长度 width的QVectorQColor每像素一行对应一个颜色。2.4 GetColorLocat — 色条最终输出调用链GetColorLocat(width)→AbstractColor(width)→ 可选二次裁剪。GetColorLocat(allnum) │ ├─ colors AbstractColor(allnum) // 已适配高度 当前 ColorType │ ├─ 若 m_MaxColor100 且 m_MinColor0 │ → 直接返回 colors全范围色条 │ └─ 否则二次裁剪 Allnum (m_MaxColor - m_MinColor) / 100 × colors.count() 从 colors 中再均匀抽取 Allnum 个颜色 → 返回 tempcolor缩短后的色条含义m_MaxColor 100、m_MinColor 0色条覆盖全高度默认。用户调FeferColorLocat如 80%m_MaxColor80色条只保留原色表的上 80% 段低密度区颜色被裁掉视觉上「热色区」压缩。BottomColorLocat控制底部裁剪两者共同定义有效色温显示区间。GetFeferData()返回m_MaxColor/100供paint做垂直偏移。2.5 paint 中绘制右侧色温条位置RtsaSpecBaseItem::paint第四步。第一步前置检查仅当Color_Y或Base_Thick时进入。若GraphRect.bottom GraphRect.top直接return区域无效。第二步计算几何参数参数值含义allnumbottom - top色条高度 绑图区像素高colorwidth20色条宽度pxrightmargin2与绑图区右边缘间距XpositionGraphRect.right 2色条左 Xstartnumtop (1-GetFeferData())×allnum垂直起始 YFefer 偏移第三步取色colors GetColorLocat(allnum)长度 allnum。第四步逐行 fillRect循环index 0 … colors.count()-1QRect(Xposition, startnum index, 20, 1)painter-fillRect(rect, colors[index])每行 1 像素高20 像素宽拼成竖直渐变色条。第五步Base_Thick 专属百分比标签调用DrawTextYAxisColor(painter, 100.0%, mode, width)mode0~4 分别对应顶、1/4、1/2、3/4、底。文字 X GraphRect.right colorwidth rightmargin与色条对齐。五档标签与GetSelectColor的四段阈值一致100%、14.9%、2.2%、0.3%、0.0%。第六步密度图复用同一 colorsDrawPointData(painter, colors)传入相同向量命中比查同一色表保证色条与密度图颜色语义一致。2.6 GetSelectColor — 命中比到颜色的非线性映射密度图每个像素的percennum 矩阵值 / maxColor0~1映射规则percennum 范围色条区间对应标签≥ 14.9% (0.149)第 1 段最热100.0%2.2% ~ 14.9%第 2 段14.9%0.3% ~ 2.2%第 3 段2.2% 0.3%第 4 段最冷0.3% / 0.0%色条被均分为 4 段everynum count/4段内线性插值索引。低频命中→冷色高频命中→暖色。2.7 色温系统数据流总图启动: AllColorData() → m_AllColor[0~5] 运行时参数: ColorSelect → m_ColorType FeferColorLocat → m_MaxColor BottomColorLocat → m_MinColor 每帧 paint: allnum 绑图高度 colors GetColorLocat(allnum) └─ AbstractColor(allnum) └─ m_AllColor[m_ColorType] 抽样/重复 └─ 按 Max/Min 二次裁剪 fillRect × allnum → 右侧色条 GetSelectColor(colors, 命中比) → 密度图 fillRect第三部分VSA 数字解调 — 星座图与眼图星座图与眼图是 VSA 数字解调两大核心分析视图二者互补定位信号质量。星座图基于 IQ 复平面每个点位对应一个传输符号主要评估幅相精度。点位集中规整代表调制质量优异点位弥散、偏移、出现杂点说明存在噪声、IQ 失衡、相位偏差、功放非线性等问题配套 EVM、MER 等指标可量化调制误差常用于发射机、射频链路故障排查。眼图由基带符号波形按时钟叠加而成侧重分析时域信号完整性。眼孔开阔、线条纤细代表码间干扰ISI、噪声、抖动小眼孔收窄、边缘粗糙、水平扩散意味着带宽不足、时序抖动大、同步异常。通过眼高、眼宽可判断噪声与时序裕量。实际测试中星座图查调制与射频失真眼图看基带与时序问题结合两项视图能快速定位数字通信链路的各类缺陷。三层图像图层内容_backgroundLayer黑底 网格 刻度_foregroundLayer星座/眼图曲线_clickedLayer鼠标点击读数3.2 数据传入格式与顺序测量端I_constellation[i]、Q_constellation[i]解调后第 i 个符号的 I/Q。ConstellationLen有效点数 N。键含义kIDataI 数组指针kQDataQ 数组指针kIQLengthNkSymRate符号率ModFormat/SymbolRate测量参数影响解调不直接传入 Draw合成 Complex索引: 0 1 2 ... N-1 I: I[0] I[1] I[2] ... I[N-1] Q: Q[0] Q[1] Q[2] ... Q[N-1] → Complex(I[i], Q[i])按符号时间顺序排列上限MaxIQLen 2002Render内再截断至 16384。Perform 归一化每帧求 I/Q 各自 min/max映射到约 [-0.9, 0.9]避免帧间幅度差导致显示缩放跳动。3.3 模式配置与颜色InitChartWidget当前配置WidgetSetModel设计意图m_pDiagramWidgetkConsole, true星座图m_pEyeWidgetkIQ, true源码为 I/Q 时域非经典眼图颜色条件含义黄色_input true星座符号间 I-Q 轨迹折线眼图折叠叠加的黄色迹线eyeInPen红色_output trueSystemControl/EyeDiagram版星座各 (I,Q) 位置 4×4 红色像素块参考/输出点3.4 星座图绘制步骤模式_isDrawConstellationtrue走DrawConstell。DrawBGLayer黑底、I/Q 网格、±1 刻度、中心十字线。坐标映射每点 iscreenX 左边距 中心X I × gainscreenY 上边距 中心Y Q × gain非正方形控件做等比例补偿超界裁剪。_inputtrue黄线连接各点≤4096 点平滑曲线否则折线→ 符号跳转轨迹。_outputtrue在 (I,Q) 处画点红块或浅绿像素取决于实现版本。DrawTicks轴标签。paintEvent合成三层 QImage。64QAMModFormat只影响解调算法UI 只接收已解调的 I/Q 序列理想时呈 8×8 点阵噪声导致扩散。3.5 眼图绘制步骤X 样本序号时间I 路、Q 路分别为绿/红折线若_isShowIPart/_isShowQPart开启。不是经典折叠眼图。经典眼图模式_isDrawEyetrue→DrawEyediagram。period _samplePerSymbol × 22 符号周期宽度。按period分段取连续 IQ 点X 段内时间槽Y 中心 I×gain。每段画一条黄色折线eyeInPen多段叠加成「眼」。_outputtrue时另有绿色输出迹线通常未开故界面只见黄色。数据要求高采样率时域 IQmeaDatI/Q当前 VSA 传的是稀疏I_constellation每符号 1 点更适合星座图。3.6 后台线程刷新DrawThread::run约 100ms 周期_isDrawBGLayer→ 重画网格。_iqDataChanged→ 拷贝 IQ →DrawFGLayer→ 更新前景。_isDrawFGLayer→ resize/切模式时强制重画。_isClickedMouse→ 点击读数框。3.7 VSA 当前代码缺口环节状态测量 → MainWindow正常Complex 合成 Render已注释ReceiveData 265–298 行SetSampleRate / SetSamplePerSymbol已注释m_pEyeWidget 模式配置为 kIQ非 kEye完整可参考Plugins/UIFIXAQPlugin中_eyeDiagram-Render()调用链。第四部分两套体系统对照维度RTSAVSA宿主TraceView GraphItemBase独立 QWidget QImage 贴图主数据Trace1 BitMap256×NkIData kQData → Complex[]颜色系统RtsaPublicFunc 6 套色温 GetSelectColor固定黄/红input/output异步TraceView 重绘回调 paintDrawThread 100ms 循环默认视图Base_ThickDisplayType4kConsole kIQ