#ifndef DATACARD_H #define DATACARD_H #include #include #include #include class QLabel; class QHBoxLayout; class QTimer; class QEvent; // ===================== 数据卡片 ===================== // 标题栏 + 若干“标签:值”行 + 一条常驻的“故障”行。 // 每行有最大高度、长到上限就停,多出来的高度归末尾弹性,所以有无故障都不改变布局; // 字段行支持红色闪烁告警;故障行没有标签、字号 kFaultFontPx,有故障时红闪、 // 多条按 1s 轮流显示,文字比整行宽时自动滑动,无故障时内容为空(行仍占位)。 class DataCard : public QWidget { Q_OBJECT public: explicit DataCard(const QString& title, QWidget* parent = nullptr); void setTitle(const QString& t); int addField(const QString& label, const QString& value = "--", bool big = false); void setField(int index, const QString& value); void setAlarm(int index, bool on); void setFaults(const QStringList& faults); // 故障行内容(空 = 清空文字,行仍占位) // 数值行字号。要在 addField 之前调——字号是建标签时就写进行内样式表的,改不了已建的。 // big 字段不走这个值(固定 50)。 void setValueFontPx(int px) { m_valueFontPx = px; } void setHighlight(bool on); // 主色描边突出 void indentRows(); // 字段行整体缩进到「中间偏左」(行首 : 行尾 = 2 : 3),只需调用一次 protected: bool eventFilter(QObject* obj, QEvent* ev) override; // 盯故障数值标签的宽度变化 private slots: void rotateFault(); void tickFaultScroll(); // 故障文字滑动一拍 private: void ensureFaultRow(); void applyFaultText(); // 设文字、量宽度、决定要不要滑动 void updateFaultScroll(); // 放得下就停着显示,放不下才开滑动 void positionFaultLabel(); // 按当前偏移摆放故障标签 QLabel* m_title = nullptr; QHBoxLayout* m_faultRow = nullptr; // 构造函数里就建好,永远占着最后一行 QWidget* m_faultBox = nullptr; // 裁剪容器:文字超宽时标签在这里面左移 QLabel* m_faultValue = nullptr; // 无“故障:”标签;宽度按文字自然宽度,位置手动给 QTimer* m_faultTimer = nullptr; // 多条故障 1s 轮换 QTimer* m_scrollTimer = nullptr; // 滑动节拍 QStringList m_faults; // 当前故障列表,空 = 无故障 QString m_faultText; // 当前该显示的完整文字 int m_faultIdx = 0; int m_textW = 0; // 当前故障文字的像素宽 int m_offset = 0; // 已左移的像素 QVector m_values; QVector m_labels; int m_valueFontPx = 42; // 数值行字号;big 字段固定 50,不受它影响 }; #endif // DATACARD_H