#include "P601_TransportPage.h" #include "ui_P601_TransportPage.h" #include #include P601_TransportPage::P601_TransportPage(QWidget *parent) : QWidget(parent), ui(new Ui::P601_TransportPage) { ui->setupUi(this); // QTimer::singleShot(1000, this, &P601_TransportPage::WinInit); // QTimer::singleShot(2000, this, &P601_TransportPage::Show3D); } P601_TransportPage::~P601_TransportPage() { delete ui; } void P601_TransportPage::WinInit(){ for (int row = 1; row < TransportConditionConfigFile.size()-1; ++row) { QString TextObjName = QString("Transport_SSConditions_%1").arg(row); QLabel* Label = findChild(TextObjName); if (Label) { QString Text = TransportConditionConfigFile.at(row)[1]; Text.replace("\\n","\n",Qt::CaseInsensitive); Label->setText(Text); } TrueColor.append(TransportConditionConfigFile.at(row)[2]); FalseColor.append(TransportConditionConfigFile.at(row)[3]); } // 现在 ui->Transport_CPW_1 已经是一个 CurvePlotWidget* ui->Transport_CPW_L1->addSeries("左U", Qt::green); ui->Transport_CPW_L1->addSeries("左V", Qt::blue); ui->Transport_CPW_L1->addSeries("左W", Qt::darkCyan); // 现在 ui->Transport_CPW_1 已经是一个 CurvePlotWidget* ui->Transport_CPW_L2->addSeries("左温", Qt::green); // 现在 ui->Transport_CPW_1 已经是一个 CurvePlotWidget* ui->Transport_CPW_R1->addSeries("右U", Qt::green); ui->Transport_CPW_R1->addSeries("右V", Qt::blue); ui->Transport_CPW_R1->addSeries("右W", Qt::darkCyan); // 现在 ui->Transport_CPW_1 已经是一个 CurvePlotWidget* ui->Transport_CPW_R2->addSeries("右温", Qt::green); //所用定时器初始化 QTimer* UIRefresh_Timer = new QTimer(this); connect(UIRefresh_Timer, &QTimer::timeout, this, &P601_TransportPage::UIRefreshTimeOut); UIRefresh_Timer->setInterval(100); // 设置定时器间隔为 1000 毫秒(1 秒) UIRefresh_Timer->start(); //所用定时器初始化 QTimer* TrailRefresh_Timer = new QTimer(this); connect(TrailRefresh_Timer, &QTimer::timeout, this, &P601_TransportPage::TrailRefreshTimeOut); TrailRefresh_Timer->setInterval(10000); // 设置定时器间隔为 1000 毫秒(1 秒) TrailRefresh_Timer->start(); } void P601_TransportPage::Show3D() { DevName3D = "运输、铲板电机"; mObjLoader = new ObjLoader(); mObjLoader->setEnDebug(true); mObjLoader->init3DScene(ui->Frame_Dev3D); mObjLoader->setCameraSpeed(200.0, 200.0); // 准备模型路径 QString filePath = ConfigurationPath + "3D模型文件/掘锚一体机/电机/" + DevName3D + ".obj"; m_currentDevName = DevName3D; m_currentFilePath = filePath; m_currentPosition = QVector3D(356.67, 65.0579, -0.231415); // 检查文件是否存在 if (!QFile::exists(filePath)) { qCritical() << "模型文件不存在: " << filePath; return; } // 创建工作线程和工作对象 m_workerThread = new QThread(this); m_workerLoader = new ObjLoader(); // 专用预处理加载器 // 移动工作对象到工作线程 m_workerLoader->moveToThread(m_workerThread); // 连接信号槽 connect(m_workerThread, &QThread::started, [=]() { // 在工作线程中预处理模型(仅计算中心和半径) QVector3D center = m_workerLoader->parseObjCenter(filePath); float radius = m_workerLoader->calculateModelRadiusFromFile(filePath); emit preprocessFinished(center, radius); }); // 预处理完成后,在主线程加载模型 connect(this, &P601_TransportPage::preprocessFinished, this, [=](QVector3D center, float radius) { m_modelCenter = center; m_modelRadius = radius; // 使用定时器确保在主线程事件循环中执行 QTimer::singleShot(0, this, [=]() { emit loadModelRequest(m_currentDevName, m_currentFilePath, center, radius); }); // 清理工作线程 m_workerThread->quit(); m_workerThread->wait(); m_workerLoader->deleteLater(); }); // 主线程中实际加载模型 connect(this, &P601_TransportPage::loadModelRequest, this, [=](const QString& devName, const QString& filePath, QVector3D center, float radius) { bool TransportOK = mObjLoader->loadModelAsync(devName, filePath, QVector3D(0, 0, 0), center, radius); if (!TransportOK) { qCritical() << "装载电机加载:失败"; return; } mObjLoader->addAxisGizmo(nullptr, 5.0f); mObjLoader->addAxisGizmo(mObjLoader->getDevice(devName)->entity, 3.0f); SetPos(0.005,QVector3D(356.67, 65.0579, -0.231415),QVector3D(0, 0, 0)); if (TransportOK) { QTimer *RotateDev_Timer = new QTimer(this); connect(RotateDev_Timer, &QTimer::timeout, this, &P601_TransportPage::RotateDev); RotateDev_Timer->setInterval(33); RotateDev_Timer->start(); } }); // 启动工作线程 m_workerThread->start(); } void P601_TransportPage::SetPos(float Zoom,QVector3D Move,QVector3D Pos){ mObjLoader->scaleDevice(DevName3D,Zoom); mObjLoader->moveArmLocalOriginTo(DevName3D, Move);//14.1, -1.4, 3.4 mObjLoader->setParentDevicePosition(DevName3D, Pos); // 世界坐标 // 6. 重置相机(确保能看到所有设备) Qt3DRender::QCamera* cam = mObjLoader->getCamera(); if (cam) { cam->setPosition(QVector3D(0, 3, 12)); // 相机在 Z 轴 30 位置,远离模型 cam->setViewCenter(QVector3D(0, 0, 0)); // 看向电控箱体的世界位置 } } void P601_TransportPage::SetProgressBar(QProgressBar *PB,const uint16_t Value,const uint8_t ColorIndex,const QStringList Color){ PB->setValue(Value); if(ColorIndex < Color.length()){ PB->setStyleSheet("QProgressBar {\n background-color: transparent;\n border: 2px solid #888888;\n border-radius: 3px;\n}\nQProgressBar::chunk {\n background-color:"+Color[ColorIndex]+";\n}"); } } void P601_TransportPage::SetProgressBar(QProgressBar *PB,QLCDNumber *LCD,const QString NodeGroup,const QString NodeLCD,const QStringList Color){ // 从OPC节点获取油位显示组数据(32位无符号整数) uint32_t PB_Group = getNodeValue("" + NodeGroup).toUInt(); // 从32位数据中拆分出16位油位百分比值和颜色值 uint16_t Percentage = static_cast(PB_Group >> 16); // 高16位:百分比 uint16_t ColorIndex = static_cast(PB_Group & 0xFFFF); // 低16位:颜色值索引 // 设置油位进度条显示(百分比、颜色和样式) SetProgressBar(PB, Percentage, ColorIndex, Color); // 在LCD上显示实际油位测量值 LCD->display(getNodeValue("" +NodeLCD).toReal()); } void P601_TransportPage::UIRefreshTimeOut() { if(!gPageIndexStr.contains("P06")) return; /************************************* 电机基本信息 *************************************/ // 从OPC节点获取切割设备电机相关的状态数据(32位无符号整数) uint32_t PB_GroupL1 = getNodeValue("PB_Curr_TransportL.PageGroup1").toUInt(); // 电流显示组1数据 uint32_t PB_GroupL2 = getNodeValue("PB_Curr_TransportL.PageGroup2").toUInt(); // 电流显示组2数据 uint32_t PB_MotorTempL = getNodeValue("PB_Temp_TransportL.PageGroup").toUInt(); // 电机温度显示数据 // 从32位数据中提取16位百分比值(高16位和低16位拆分) uint16_t PercentageCurLU = static_cast(PB_GroupL1 >> 16); // U相电流百分比(高16位) uint16_t PercentageCurLV = static_cast(PB_GroupL1 & 0xFFFF); // V相电流百分比(低16位) uint16_t PercentageCurLW = static_cast(PB_GroupL2 >> 16); // W相电流百分比(高16位) uint16_t PercentageTmpColorL = static_cast(PB_GroupL2 & 0xFFFF); // 温度颜色百分比(低16位) uint16_t PercentageMotorTempL= static_cast(PB_MotorTempL >> 16); // 电机温度百分比(高16位) uint16_t ColorTempL = static_cast(PB_MotorTempL & 0xFFFF); // 温度颜色值(低16位) // 解析颜色值(从百分比中提取个位、十位、百位) uint8_t ColorLU = (PercentageTmpColorL / 10) % 10; // U相颜色值(十位) uint8_t ColorLV = (PercentageTmpColorL / 100) % 10; // V相颜色值(百位) uint8_t ColorLW = PercentageTmpColorL % 10; // W相颜色值(个位) // 设置进度条显示(电流和温度) SetProgressBar(ui->PB_CurL_1, PercentageCurLU, ColorLU, glMotorCurColor); // U相电流进度条 SetProgressBar(ui->PB_CurL_2, PercentageCurLV, ColorLV, glMotorCurColor); // V相电流进度条 SetProgressBar(ui->PB_CurL_3, PercentageCurLW, ColorLW, glMotorCurColor); // W相电流进度条 SetProgressBar(ui->PB_TempL, PercentageMotorTempL, ColorTempL, glMotorTempColor); // 电机温度进度条 // 在LCD上显示实际测量值(电流和温度) ui->LCD_CurL_1->display(getNodeValue("IN_PhaseTransportL.Filtered30_U").toReal()); // U相电流实际值 ui->LCD_CurL_2->display(getNodeValue("IN_PhaseTransportL.Filtered30_V").toReal()); // V相电流实际值 ui->LCD_CurL_3->display(getNodeValue("IN_PhaseTransportL.Filtered30_W").toReal()); // W相电流实际值 ui->LCD_TempL->display(getNodeValue("IN_PhaseTransportL.Filtered_Temp").toReal()); // 电机温度实际值 /**************************************************************************************/ /************************************* 电机基本信息 *************************************/ // 从OPC节点获取切割设备电机相关的状态数据(32位无符号整数) uint32_t PB_GroupR1 = getNodeValue("PB_Curr_TransportR.PageGroup1").toUInt(); // 电流显示组1数据 uint32_t PB_GroupR2 = getNodeValue("PB_Curr_TransportR.PageGroup2").toUInt(); // 电流显示组2数据 uint32_t PB_MotorTempR = getNodeValue("PB_Temp_TransportR.PageGroup").toUInt(); // 电机温度显示数据 // 从32位数据中提取16位百分比值(高16位和低16位拆分) uint16_t PercentageCurRU = static_cast(PB_GroupR1 >> 16); // U相电流百分比(高16位) uint16_t PercentageCurRV = static_cast(PB_GroupR1 & 0xFFFF); // V相电流百分比(低16位) uint16_t PercentageCurRW = static_cast(PB_GroupR2 >> 16); // W相电流百分比(高16位) uint16_t PercentageTmpColorR = static_cast(PB_GroupR2 & 0xFFFF); // 温度颜色百分比(低16位) uint16_t PercentageMotorTempR= static_cast(PB_MotorTempR >> 16); // 电机温度百分比(高16位) uint16_t ColorTempR = static_cast(PB_MotorTempR & 0xFFFF); // 温度颜色值(低16位) // 解析颜色值(从百分比中提取个位、十位、百位) uint8_t ColorRU = (PercentageTmpColorR / 10) % 10; // U相颜色值(十位) uint8_t ColorRV = (PercentageTmpColorR / 100) % 10; // V相颜色值(百位) uint8_t ColorRW = PercentageTmpColorR % 10; // W相颜色值(个位) // 设置进度条显示(电流和温度) SetProgressBar(ui->PB_CurR_1, PercentageCurRU, ColorRU, glMotorCurColor); // U相电流进度条 SetProgressBar(ui->PB_CurR_2, PercentageCurRV, ColorRV, glMotorCurColor); // V相电流进度条 SetProgressBar(ui->PB_CurR_3, PercentageCurRW, ColorRW, glMotorCurColor); // W相电流进度条 SetProgressBar(ui->PB_TempR, PercentageMotorTempR, ColorTempR, glMotorTempColor); // 电机温度进度条 // 在LCD上显示实际测量值(电流和温度) ui->LCD_CurR_1->display(getNodeValue("IN_PhaseTransportR.Filtered30_U").toReal()); // U相电流实际值 ui->LCD_CurR_2->display(getNodeValue("IN_PhaseTransportR.Filtered30_V").toReal()); // V相电流实际值 ui->LCD_CurR_3->display(getNodeValue("IN_PhaseTransportR.Filtered30_W").toReal()); // W相电流实际值 ui->LCD_TempR->display(getNodeValue("IN_PhaseTransportR.Filtered_Temp").toReal()); // 电机温度实际值 /**************************************************************************************/ /************************************* 启停条件信息 *************************************/ uint32_t SSConditions = getNodeValue("StartStopConditions.Transport").toUInt(); // 启停条件状态数据 // 更新32个启停条件状态标签的显示样式 for (int i = 0; i < 32; ++i) { // 根据索引查找对应的标签控件 QLabel* Label = findChild(QString("Transport_SSConditions_%1").arg(i+1)); // 如果找到标签 if (Label){ // 基础样式:默认背景图 QString StyleStr = "border-image: url(:/Frames/null.png);\n"; // 根据状态位设置不同颜色(True/False对应不同样式) StyleStr += getBitOf32Data(SSConditions, i, false) ? TrueColor[i] + "\n" : FalseColor[i] + "\n"; // 应用样式到标签 Label->setStyleSheet(StyleStr); } } /**************************************************************************************/ } void P601_TransportPage::TrailRefreshTimeOut(){ ui->Transport_CPW_L1->appendPoint(0, getNodeValue("IN_PhaseTransportL.Filtered30_U") .toReal()); ui->Transport_CPW_L1->appendPoint(1, getNodeValue("IN_PhaseTransportL.Filtered30_V") .toReal()); ui->Transport_CPW_L1->appendPoint(2, getNodeValue("IN_PhaseTransportL.Filtered30_W") .toReal()); ui->Transport_CPW_L2->appendPoint(0,getNodeValue("IN_PhaseTransportL.Filtered_Temp") .toDouble()); ui->Transport_CPW_R1->appendPoint(0, getNodeValue("IN_PhaseTransportR.Filtered30_U") .toReal()); ui->Transport_CPW_R1->appendPoint(1, getNodeValue("IN_PhaseTransportR.Filtered30_V") .toReal()); ui->Transport_CPW_R1->appendPoint(2, getNodeValue("IN_PhaseTransportR.Filtered30_W") .toReal()); ui->Transport_CPW_R2->appendPoint(0,getNodeValue("IN_PhaseTransportR.Filtered_Temp") .toDouble()); } void P601_TransportPage::RotateDev(){ if(!gPageIndexStr.contains("P601")) return; mAngle = mAngle + 1; if(mAngle > 360) mAngle =0; mObjLoader->rotateArmToAbsoluteYAngle(DevName3D, mAngle); }