更新UI
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#include "Basic.h"
|
||||
|
||||
#include <QColor>
|
||||
|
||||
/**
|
||||
* @brief map 映射函数,把x的值,映射到out_min到out_max的范围内
|
||||
@@ -173,4 +173,99 @@ uint16_t extractUInt32_16BitPart(uint32_t data, int index) {
|
||||
return 00;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief getNodeValue 获取节点内的值
|
||||
* @param nodeId 欲获取的节点文本
|
||||
* @return 类型:QVariant 节点的值
|
||||
*/
|
||||
QVariant getNodeValue(const QString &nodeId){
|
||||
QString mNodeID = nodeId;
|
||||
if(!mNodeID.contains("ns=6;s=::AsGlobalPV:"))
|
||||
mNodeID = "ns=6;s=::AsGlobalPV:"+mNodeID;
|
||||
return gOPC_NodeValue[mNodeID];
|
||||
}
|
||||
/**
|
||||
* @brief getColorStr 获取颜色文本
|
||||
* @param Str 欲获取的文本内容
|
||||
* @return 返回颜色文本
|
||||
*/
|
||||
QString getColorStr(QString str)
|
||||
{
|
||||
|
||||
/*
|
||||
颜色文本的表现形式:
|
||||
color: rgb(255, 0, 0);
|
||||
color: #ff0000;
|
||||
颜色文本格式:
|
||||
color: rgb(255, 0, 0);
|
||||
color: rgb(255, 0, 0)
|
||||
rgb(255, 0, 0)
|
||||
rgb(255, 0, 0);
|
||||
255, 0, 0
|
||||
255, 0, 0;
|
||||
|
||||
color: #ff0000
|
||||
color: #ff0000;
|
||||
#ff0000
|
||||
#ff0000;
|
||||
ff0000
|
||||
ff0000;
|
||||
*/
|
||||
str = str.trimmed();
|
||||
|
||||
/* 1. 先尝试匹配 rgb(r, g, b) 形式 */
|
||||
static QRegularExpression reRgb(
|
||||
R"(^\s*(?:color\s*:\s*)?rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\);?\s*$)",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
auto match = reRgb.match(str);
|
||||
if (match.hasMatch()) {
|
||||
int r = match.captured(1).toInt();
|
||||
int g = match.captured(2).toInt();
|
||||
int b = match.captured(3).toInt();
|
||||
return QString("color: rgb(%1, %2, %3);").arg(r).arg(g).arg(b);
|
||||
}
|
||||
|
||||
/* 2. 再尝试匹配 #hex 或裸 hex 形式 */
|
||||
static QRegularExpression reHex(
|
||||
R"(^\s*(?:color\s*:\s*)?(?:#)?([0-9a-f]{6});?\s*$)",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
match = reHex.match(str);
|
||||
if (match.hasMatch()) {
|
||||
QString hex = match.captured(1).toLower();
|
||||
return QString("color: #%1;").arg(hex);
|
||||
}
|
||||
|
||||
/* 3. 都不符合,原样返回(或按需返回空串) */
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* @brief getColor
|
||||
* @param str 任意颜色字符串
|
||||
* @return QColor(无效 QColor 表示解析失败)
|
||||
*/
|
||||
QColor getColor(const QString &str)
|
||||
{
|
||||
QString s = str.trimmed();
|
||||
|
||||
/* 1. rgb(r, g, b) */
|
||||
static QRegularExpression reRgb(
|
||||
R"(^\s*(?:color\s*:\s*)?rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\);?\s*$)",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
auto m = reRgb.match(s);
|
||||
if (m.hasMatch()) {
|
||||
int r = m.captured(1).toInt();
|
||||
int g = m.captured(2).toInt();
|
||||
int b = m.captured(3).toInt();
|
||||
return QColor(r, g, b);
|
||||
}
|
||||
|
||||
/* 2. #RRGGBB 或 RRGGBB */
|
||||
static QRegularExpression reHex(
|
||||
R"(^\s*(?:color\s*:\s*)?(?:#)?([0-9a-fA-F]{6});?\s*$)");
|
||||
m = reHex.match(s);
|
||||
if (m.hasMatch())
|
||||
return QColor('#' + m.captured(1)); // QColor 接受 "#ff0000"
|
||||
|
||||
/* 3. 解析失败 */
|
||||
return QColor(); // 无效颜色
|
||||
}
|
||||
|
||||
176
PublicFunctions/Basic.cpp.bak
Normal file
176
PublicFunctions/Basic.cpp.bak
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "Basic.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief map 映射函数,把x的值,映射到out_min到out_max的范围内
|
||||
* @param x 需要映射的值
|
||||
* @param in_min x有可能的最小值
|
||||
* @param in_max x有可能的最大值
|
||||
* @param out_min 输出的最小值
|
||||
* @param out_max 输出的最大值
|
||||
* @return 映射结果
|
||||
*/
|
||||
M_d64 map(M_d64 x, M_d64 in_min, M_d64 in_max, M_d64 out_min, M_d64 out_max) {
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
/**
|
||||
* @brief Sleep_ms 不占用线程的延时函数
|
||||
* @param msec 需要延时的毫秒数
|
||||
*/
|
||||
void Sleep_ms(M_u16 msec){
|
||||
QTime _Timer = QTime::currentTime().addMSecs(msec);
|
||||
while( QTime::currentTime() < _Timer )
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取 32 位数据的第 N 位状态
|
||||
* @param data 32 位数据源(支持 uint32_t 或 int32_t)
|
||||
* @param bitIndex 位索引(0 = 最低位/第1位,31 = 最高位/第32位)
|
||||
* @param defaultValue 索引越界时的默认返回值(默认 false)
|
||||
* @return bool 位状态:true = 1,false = 0
|
||||
*/
|
||||
bool getBitOf32Data(uint32_t data, int bitIndex, bool defaultValue)
|
||||
{
|
||||
// 1. 边界检查:32位数据的索引范围是 0~31,超出则返回默认值
|
||||
if (bitIndex < 0 || bitIndex > 31) {
|
||||
qWarning() << "[getBitOf32Data] 位索引越界!当前索引:" << bitIndex
|
||||
<< ",允许范围:0~31";
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// 2. 位运算核心逻辑:
|
||||
// - (1U << bitIndex):生成“指定位为1,其他位为0”的掩码(1U 确保无符号移位,避免符号位问题)
|
||||
// - (data & 掩码):按位与操作,若结果非0,说明指定位为1;否则为0
|
||||
return (static_cast<uint32_t>(data) & (1U << bitIndex)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将 32 位数据的第 N 位设为 1
|
||||
* @param data 原始 32 位数据(按引用修改)
|
||||
* @param bitIndex 位索引(0 = 最低位,31 = 最高位)
|
||||
* @return bool 成功返回 true;若索引越界返回 false,且不修改 data
|
||||
*/
|
||||
bool setBitOf32Data(uint32_t &data, int bitIndex)
|
||||
{
|
||||
if (bitIndex < 0 || bitIndex > 31) {
|
||||
qWarning().noquote() << "[setBitOf32Data] 位索引越界!索引:" << bitIndex;
|
||||
return false;
|
||||
}
|
||||
data |= (1U << bitIndex); // 置 1
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将 32 位数据的第 N 位清 0
|
||||
* @param data 原始 32 位数据(按引用修改)
|
||||
* @param bitIndex 位索引(0 = 最低位,31 = 最高位)
|
||||
* @return bool 成功返回 true;若索引越界返回 false,且不修改 data
|
||||
*/
|
||||
bool clearBitOf32Data(uint32_t &data, int bitIndex)
|
||||
{
|
||||
if (bitIndex < 0 || bitIndex > 31) {
|
||||
qWarning().noquote() << "[clearBitOf32Data] 位索引越界!索引:" << bitIndex;
|
||||
return false;
|
||||
}
|
||||
data &= ~(1U << bitIndex); // 清 0
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将 32 位数据的第 N 位设为指定状态
|
||||
* @param data 原始 32 位数据(按引用修改)
|
||||
* @param bitIndex 位索引(0 = 最低位,31 = 最高位)
|
||||
* @param bitValue 要写入的位值:true = 1,false = 0
|
||||
* @return bool 成功返回 true;若索引越界返回 false,且不修改 data
|
||||
*/
|
||||
bool writeBitOf32Data(uint32_t &data, int bitIndex, bool bitValue)
|
||||
{
|
||||
return bitValue ? setBitOf32Data(data, bitIndex)
|
||||
: clearBitOf32Data(data, bitIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将 QVariant 按“先转字符串判断小数点”逻辑格式化
|
||||
* @param variant:待转换的 QVariant 数据
|
||||
* @param decimalDigits:需要保留的小数位数(默认2位,可自定义)
|
||||
* @return 格式化后的字符串
|
||||
*/
|
||||
QString variantToFormattedString(const QVariant& variant, int decimalDigits) {
|
||||
// 1. 安全校验:小数位数不能为负数
|
||||
if (decimalDigits < 0) {
|
||||
decimalDigits = 0;
|
||||
}
|
||||
|
||||
// 2. 第一步:先将 QVariant 转为原始字符串(不做任何数值格式化)
|
||||
QString originalStr = variant.toString();
|
||||
// 处理空字符串情况
|
||||
if (originalStr.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// 3. 第二步:过滤非数字字符串(仅对数字字符串做小数处理)
|
||||
// 正则匹配:整数(如 "123"、"-456")或浮点数(如 "123.45"、".67"、"89.")
|
||||
QRegExp numRegExp("^-?\\d+(\\.\\d*)?$");
|
||||
if (!numRegExp.exactMatch(originalStr)) {
|
||||
return originalStr;
|
||||
}
|
||||
|
||||
// 4. 第三步:判断字符串是否含小数点,按需格式化
|
||||
if (originalStr.contains('.')) {
|
||||
// 有小数点:解析为浮点数,保留指定小数位数(四舍五入)
|
||||
bool ok = false;
|
||||
double num = originalStr.toDouble(&ok);
|
||||
if (ok) {
|
||||
// 用 'f' 格式确保固定小数位数(如 decimalDigits=3 时,123.4→123.400)
|
||||
return QString::number(num, 'f', decimalDigits);
|
||||
} else {
|
||||
// 极端情况:匹配正则但无法解析(如 ".abc",实际正则已过滤),返回原字符串
|
||||
return originalStr;
|
||||
}
|
||||
} else {
|
||||
// 无小数点:直接返回原始整数字符串(不受小数位数影响)
|
||||
return originalStr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过索引提取uint32_t的8位部分
|
||||
* @param data 要提取的32位无符号整数
|
||||
* @param index 索引:0=HH(高8位), 1=HL(次高8位), 2=LH(次低8位), 3=LL(低8位)
|
||||
* @return 对应的8位部分
|
||||
* @throws std::out_of_range 当索引超出0-3范围时
|
||||
*/
|
||||
uint8_t extractUInt32_8BitPart(uint32_t data, uint8_t index) {
|
||||
switch(index) {
|
||||
case 0: // HH - 高8位
|
||||
return (data >> 24) & 0xFF;
|
||||
case 1: // HL - 次高8位
|
||||
return (data >> 16) & 0xFF;
|
||||
case 2: // LH - 次低8位
|
||||
return (data >> 8) & 0xFF;
|
||||
case 3: // LL - 低8位
|
||||
return data & 0xFF;
|
||||
default:
|
||||
return 00;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过索引提取uint32_t的16位部分
|
||||
* @param data 要提取的32位无符号整数
|
||||
* @param index 索引:0=高16位, 1=低16位
|
||||
* @return 对应的16位部分(uint16_t类型)
|
||||
* @throws std::out_of_range 当索引超出0-1范围时
|
||||
*/
|
||||
uint16_t extractUInt32_16BitPart(uint32_t data, int index) {
|
||||
switch(index) {
|
||||
case 0: // 高16位
|
||||
return static_cast<uint16_t>((data >> 16) & 0xFFFF);
|
||||
case 1: // 低16位
|
||||
return static_cast<uint16_t>(data & 0xFFFF);
|
||||
default:
|
||||
return 00;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#ifndef BASIC_H
|
||||
#define BASIC_H
|
||||
#include <GlobalDefinitions/DataType.h>
|
||||
#include <GlobalDefinitions/Variable.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QTime>
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
/**
|
||||
* @brief map 映射函数,把x的值,映射到out_min到out_max的范围内
|
||||
@@ -81,4 +82,25 @@ uint8_t extractUInt32_8BitPart(uint32_t data, uint8_t index);
|
||||
* @throws std::out_of_range 当索引超出0-1范围时
|
||||
*/
|
||||
uint16_t extractUInt32_16BitPart(uint32_t data, int index);
|
||||
|
||||
/**
|
||||
* @brief getNodeValue 获取节点内的值
|
||||
* @param nodeId 欲获取的节点文本
|
||||
* @return 类型:QVariant 节点的值
|
||||
*/
|
||||
QVariant getNodeValue(const QString &nodeId);
|
||||
|
||||
/**
|
||||
* @brief getColorStr 获取颜色文本
|
||||
* @param Str 欲获取的文本内容
|
||||
* @return 返回颜色文本
|
||||
*/
|
||||
QString getColorStr(QString Str);
|
||||
|
||||
/**
|
||||
* @brief getColor
|
||||
* @param str 任意颜色字符串
|
||||
* @return QColor(无效 QColor 表示解析失败)
|
||||
*/
|
||||
QColor getColor(const QString &str);
|
||||
#endif // BASIC_H
|
||||
|
||||
84
PublicFunctions/Basic.h.bak
Normal file
84
PublicFunctions/Basic.h.bak
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef BASIC_H
|
||||
#define BASIC_H
|
||||
#include <GlobalDefinitions/DataType.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QTime>
|
||||
|
||||
|
||||
/**
|
||||
* @brief map 映射函数,把x的值,映射到out_min到out_max的范围内
|
||||
* @param x 需要映射的值
|
||||
* @param in_min x有可能的最小值
|
||||
* @param in_max x有可能的最大值
|
||||
* @param out_min 输出的最小值
|
||||
* @param out_max 输出的最大值
|
||||
* @return 映射结果
|
||||
*/
|
||||
M_d64 map(M_d64 x, M_d64 in_min, M_d64 in_max, M_d64 out_min, M_d64 out_max);
|
||||
|
||||
/**
|
||||
* @brief Sleep_ms 不占用线程的延时函数
|
||||
* @param msec 需要延时的毫秒数
|
||||
*/
|
||||
void Sleep_ms(M_u16 msec);
|
||||
|
||||
/**
|
||||
* @brief 获取 32 位数据的第 N 位状态
|
||||
* @param data 32 位数据源(支持 uint32_t 或 int32_t)
|
||||
* @param bitIndex 位索引(0 = 最低位/第1位,31 = 最高位/第32位)
|
||||
* @param defaultValue 索引越界时的默认返回值(默认 false)
|
||||
* @return bool 位状态:true = 1,false = 0
|
||||
*/
|
||||
bool getBitOf32Data(uint32_t data, int bitIndex, bool defaultValue = false);
|
||||
|
||||
/**
|
||||
* @brief 将 32 位数据的第 N 位设为 1
|
||||
* @param data 原始 32 位数据(按引用修改)
|
||||
* @param bitIndex 位索引(0 = 最低位,31 = 最高位)
|
||||
* @return bool 成功返回 true;若索引越界返回 false,且不修改 data
|
||||
*/
|
||||
bool setBitOf32Data(uint32_t &data, int bitIndex);
|
||||
|
||||
/**
|
||||
* @brief 将 32 位数据的第 N 位清 0
|
||||
* @param data 原始 32 位数据(按引用修改)
|
||||
* @param bitIndex 位索引(0 = 最低位,31 = 最高位)
|
||||
* @return bool 成功返回 true;若索引越界返回 false,且不修改 data
|
||||
*/
|
||||
bool clearBitOf32Data(uint32_t &data, int bitIndex);
|
||||
|
||||
/**
|
||||
* @brief 将 32 位数据的第 N 位设为指定状态
|
||||
* @param data 原始 32 位数据(按引用修改)
|
||||
* @param bitIndex 位索引(0 = 最低位,31 = 最高位)
|
||||
* @param bitValue 要写入的位值:true = 1,false = 0
|
||||
* @return bool 成功返回 true;若索引越界返回 false,且不修改 data
|
||||
*/
|
||||
bool writeBitOf32Data(uint32_t &data, int bitIndex, bool bitValue);
|
||||
|
||||
/**
|
||||
* @brief 将 QVariant 按“先转字符串判断小数点”逻辑格式化
|
||||
* @param variant:待转换的 QVariant 数据
|
||||
* @param decimalDigits:需要保留的小数位数(默认2位,可自定义)
|
||||
* @return 格式化后的字符串
|
||||
*/
|
||||
QString variantToFormattedString(const QVariant& variant, int decimalDigits);
|
||||
|
||||
/**
|
||||
* 通过索引提取uint32_t的8位部分
|
||||
* @param data 要提取的32位无符号整数
|
||||
* @param index 索引:0=HH(高8位), 1=HL(次高8位), 2=LH(次低8位), 3=LL(低8位)
|
||||
* @return 对应的8位部分
|
||||
* @throws std::out_of_range 当索引超出0-3范围时
|
||||
*/
|
||||
uint8_t extractUInt32_8BitPart(uint32_t data, uint8_t index);
|
||||
|
||||
/**
|
||||
* 通过索引提取uint32_t的16位部分
|
||||
* @param data 要提取的32位无符号整数
|
||||
* @param index 索引:0=高16位, 1=低16位
|
||||
* @return 对应的16位部分(uint16_t类型)
|
||||
* @throws std::out_of_range 当索引超出0-1范围时
|
||||
*/
|
||||
uint16_t extractUInt32_16BitPart(uint32_t data, int index);
|
||||
#endif // BASIC_H
|
||||
@@ -40,37 +40,25 @@ ObjLoader::ObjLoader(QObject *parent)
|
||||
*/
|
||||
ObjLoader::~ObjLoader()
|
||||
{
|
||||
// 1. 先销毁所有子模型(避免父模型先销毁导致子模型悬空)
|
||||
QVector<QString> childDeviceNames;
|
||||
for (const auto& device : m_deviceMap) {
|
||||
if (!device.parentDeviceName.isEmpty()) {
|
||||
childDeviceNames.append(device.name);
|
||||
}
|
||||
}
|
||||
for (const auto& childName : childDeviceNames) {
|
||||
auto it = m_deviceMap.find(childName);
|
||||
if (it != m_deviceMap.end()) {
|
||||
delete it->modelTransform;
|
||||
delete it->transform;
|
||||
delete it->modelEntity;
|
||||
delete it->entity;
|
||||
m_deviceMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 再销毁父模型
|
||||
for (auto &device : m_deviceMap) {
|
||||
delete device.modelTransform;
|
||||
delete device.transform;
|
||||
delete device.modelEntity;
|
||||
delete device.entity;
|
||||
// 安全清理:避免双重删除和悬空指针
|
||||
|
||||
// 1. 停止动画定时器
|
||||
if (m_animTimer) {
|
||||
m_animTimer->stop();
|
||||
m_animTimer->deleteLater();
|
||||
m_animTimer = nullptr;
|
||||
}
|
||||
|
||||
// 2. 清理设备映射表(Qt3D对象由Qt框架自动管理,不要手动delete)
|
||||
m_deviceMap.clear();
|
||||
|
||||
// 3. 清理场景资源
|
||||
delete m_wholeModelEntity;
|
||||
delete m_rootEntity;
|
||||
delete m_3dView;
|
||||
|
||||
// 3. 清理场景资源(设置为nullptr,Qt框架会自动管理)
|
||||
m_wholeModelEntity = nullptr;
|
||||
m_rootEntity = nullptr;
|
||||
|
||||
// 4. 3D窗口由Qt容器管理,不要手动删除
|
||||
m_3dView = nullptr;
|
||||
m_viewContainer = nullptr;
|
||||
}
|
||||
/**
|
||||
* @brief ObjLoader::setEnDebug 是否启用qDebug打印信息
|
||||
|
||||
Reference in New Issue
Block a user