2025-08-20 23:06:28 +08:00
|
|
|
|
#include "P00_PublicPage.h"
|
|
|
|
|
|
#include "ui_P00_PublicPage.h"
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
|
#include <QMovie>
|
2025-09-15 22:28:43 +08:00
|
|
|
|
#include <type_traits>
|
|
|
|
|
|
#include <FileOperation/ConfigFiles.h>
|
|
|
|
|
|
#include <PublicFunctions/TTSManager.h>
|
|
|
|
|
|
#include <QKeyEvent>
|
|
|
|
|
|
|
2025-09-28 17:14:34 +08:00
|
|
|
|
#include <QPropertyAnimation>
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
2025-08-20 23:06:28 +08:00
|
|
|
|
P00_PublicPage::P00_PublicPage(QWidget *parent)
|
|
|
|
|
|
: QWidget(parent)
|
|
|
|
|
|
, ui(new Ui::P00_PublicPage)
|
2025-09-15 22:28:43 +08:00
|
|
|
|
, m_opcManager(OpcUaManager::instance(this))
|
|
|
|
|
|
, m_dataCenter(DataCenter::instance(this))
|
|
|
|
|
|
, UIRefresh_Timer(nullptr)
|
|
|
|
|
|
, CursorScan_Timer(nullptr)
|
|
|
|
|
|
, PLC_Started(false)
|
2025-08-20 23:06:28 +08:00
|
|
|
|
{
|
|
|
|
|
|
ui->setupUi(this);
|
2025-10-10 17:44:10 +08:00
|
|
|
|
|
|
|
|
|
|
QTimer::singleShot(10, this, &P00_PublicPage::WinInit);
|
2025-08-20 23:06:28 +08:00
|
|
|
|
|
2025-09-15 22:28:43 +08:00
|
|
|
|
// 连接服务器
|
|
|
|
|
|
tsServerAddr tmpServerAddr = ConfigFiles::ReadServerAddr();
|
|
|
|
|
|
m_opcManager->connectToServer(tmpServerAddr.Host, tmpServerAddr.UserName, tmpServerAddr.Passwd);
|
2025-08-20 23:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
P00_PublicPage::~P00_PublicPage()
|
|
|
|
|
|
{
|
2025-09-15 22:28:43 +08:00
|
|
|
|
// 清理定时器
|
|
|
|
|
|
if (UIRefresh_Timer) {
|
|
|
|
|
|
UIRefresh_Timer->stop();
|
|
|
|
|
|
delete UIRefresh_Timer;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (CursorScan_Timer) {
|
|
|
|
|
|
CursorScan_Timer->stop();
|
|
|
|
|
|
delete CursorScan_Timer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-10 17:44:10 +08:00
|
|
|
|
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
|
|
|
|
|
// 清理缓存的窗口
|
|
|
|
|
|
qDeleteAll(m_widgetCache);
|
|
|
|
|
|
m_widgetCache.clear();
|
|
|
|
|
|
|
2025-08-20 23:06:28 +08:00
|
|
|
|
delete ui;
|
|
|
|
|
|
}
|
2025-09-28 17:14:34 +08:00
|
|
|
|
// 平滑滚动到指定位置的函数
|
|
|
|
|
|
void P00_PublicPage::smoothScrollTo(int targetX)
|
|
|
|
|
|
{
|
|
|
|
|
|
QScrollBar* hScroll = ui->scrollArea->horizontalScrollBar();
|
|
|
|
|
|
uint16_t MaxValue = ui->scrollArea->horizontalScrollBar()->maximum();
|
|
|
|
|
|
uint16_t Current = MaxValue / 15 * targetX;
|
|
|
|
|
|
if (!hScroll) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 创建属性动画,作用于滚动条的value属性
|
|
|
|
|
|
QPropertyAnimation* animation = new QPropertyAnimation(hScroll, "value", this);
|
2025-09-30 15:36:46 +08:00
|
|
|
|
animation->setDuration(600); // 动画持续时间,单位:毫秒
|
2025-09-28 17:14:34 +08:00
|
|
|
|
animation->setEasingCurve(QEasingCurve::OutQuart); // 动画曲线,使滚动更自然
|
|
|
|
|
|
animation->setStartValue(hScroll->value()); // 起始值为当前位置
|
|
|
|
|
|
animation->setEndValue(Current); // 目标位置
|
|
|
|
|
|
|
|
|
|
|
|
// 启动动画
|
|
|
|
|
|
animation->start(QAbstractAnimation::DeleteWhenStopped); // 动画结束后自动删除
|
|
|
|
|
|
}
|
2025-08-20 23:06:28 +08:00
|
|
|
|
void P00_PublicPage::CursorInit()
|
|
|
|
|
|
{
|
|
|
|
|
|
/* 自绘光标 */
|
|
|
|
|
|
m_cursorLabel = new QLabel(this);
|
|
|
|
|
|
m_cursorLabel->setPixmap(QPixmap(":/Icos/Icos/Sursor.png"));
|
|
|
|
|
|
m_cursorLabel->setFixedSize(m_cursorLabel->pixmap()->size());
|
|
|
|
|
|
m_cursorLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
|
2025-09-15 22:28:43 +08:00
|
|
|
|
m_cursorLabel->raise();
|
2025-08-20 23:06:28 +08:00
|
|
|
|
m_cursorLabel->show();
|
|
|
|
|
|
|
|
|
|
|
|
/* 光标控制器 */
|
|
|
|
|
|
gCursor = new CursorController(this);
|
|
|
|
|
|
connect(gCursor, &CursorController::cursorMoved,
|
|
|
|
|
|
this, &P00_PublicPage::onCursorMoved);
|
|
|
|
|
|
|
2025-09-15 22:28:43 +08:00
|
|
|
|
gCursor->cfg.step = 2;
|
|
|
|
|
|
gCursor->cfg.wrap = false;
|
|
|
|
|
|
gCursor->cfg.emulate = true;
|
2025-08-20 23:06:28 +08:00
|
|
|
|
setFocusPolicy(Qt::StrongFocus);
|
|
|
|
|
|
setFocus();
|
|
|
|
|
|
activateWindow();
|
|
|
|
|
|
grabKeyboard();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void P00_PublicPage::onCursorMoved(const QPoint &global)
|
|
|
|
|
|
{
|
|
|
|
|
|
QPoint local = mapFromGlobal(global);
|
|
|
|
|
|
m_cursorLabel->move(local - m_cursorLabel->rect().center());
|
|
|
|
|
|
}
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
|
|
|
|
|
void P00_PublicPage::WinInit()
|
|
|
|
|
|
{
|
2025-10-10 17:44:10 +08:00
|
|
|
|
CursorInit();
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
2025-09-30 15:36:46 +08:00
|
|
|
|
ui->Label_VoiceWidget->resize(960,0);
|
|
|
|
|
|
ui->Label_VoiceWidget->move(32,70+576/2);
|
|
|
|
|
|
ui->Label_VoiceWidget->hide();
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-08-20 23:06:28 +08:00
|
|
|
|
|
2025-09-15 22:28:43 +08:00
|
|
|
|
// 初始化定时器(作为成员变量)
|
|
|
|
|
|
UIRefresh_Timer = new QTimer(this);
|
2025-08-20 23:06:28 +08:00
|
|
|
|
connect(UIRefresh_Timer, &QTimer::timeout, this, &P00_PublicPage::UIRefreshTimeOut);
|
2025-09-15 22:28:43 +08:00
|
|
|
|
UIRefresh_Timer->setInterval(100);
|
2025-10-14 20:05:38 +08:00
|
|
|
|
//UIRefresh_Timer->start();
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
|
|
|
|
|
CursorScan_Timer = new QTimer(this);
|
2025-08-20 23:06:28 +08:00
|
|
|
|
connect(CursorScan_Timer, &QTimer::timeout, this, &P00_PublicPage::CursorScanTimerOut);
|
2025-09-15 22:28:43 +08:00
|
|
|
|
CursorScan_Timer->setInterval(50);
|
2025-08-20 23:06:28 +08:00
|
|
|
|
CursorScan_Timer->start();
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
|
|
|
|
|
#if defined(Q_OS_WIN)
|
|
|
|
|
|
ui->Label_BorderImg->setStyleSheet("border-image: url(:/Imgs/Imgs/newbg_all.png);");
|
|
|
|
|
|
ui->Label_BorderImg->setMinimumSize(QSize(1024,768));
|
|
|
|
|
|
ui->Label_BorderImg->move(0,0);
|
|
|
|
|
|
#endif
|
2025-10-10 17:44:10 +08:00
|
|
|
|
|
|
|
|
|
|
SignalSlotInit();
|
|
|
|
|
|
gPageIndexStr = "P01";
|
2025-08-20 23:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 22:28:43 +08:00
|
|
|
|
void P00_PublicPage::SignalSlotInit()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_dataCenter->initData();
|
2025-08-20 23:06:28 +08:00
|
|
|
|
connect(m_opcManager, &OpcUaManager::stateChanged,
|
2025-09-15 22:28:43 +08:00
|
|
|
|
this, &P00_PublicPage::onOpcStateChanged, Qt::QueuedConnection);
|
2025-08-20 23:06:28 +08:00
|
|
|
|
}
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
2025-08-20 23:06:28 +08:00
|
|
|
|
void P00_PublicPage::keyPressEvent(QKeyEvent *e)
|
|
|
|
|
|
{
|
2025-09-15 22:28:43 +08:00
|
|
|
|
gCursor->handleKey(e->key(), true);
|
2025-08-20 23:06:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void P00_PublicPage::onOpcStateChanged(QOpcUaClient::ClientState state)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (state) {
|
|
|
|
|
|
case QOpcUaClient::Disconnected:
|
|
|
|
|
|
ui->LED_ConnectionStatus->show();
|
|
|
|
|
|
m_dataCenter->stopCyclicRead();
|
|
|
|
|
|
PLC_Started = false;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case QOpcUaClient::Connecting:
|
|
|
|
|
|
ui->LED_ConnectionStatus->show();
|
|
|
|
|
|
m_dataCenter->stopCyclicRead();
|
|
|
|
|
|
PLC_Started = false;
|
|
|
|
|
|
break;
|
2025-09-15 22:28:43 +08:00
|
|
|
|
case QOpcUaClient::Connected:
|
2025-08-20 23:06:28 +08:00
|
|
|
|
ui->LED_ConnectionStatus->hide();
|
2025-09-15 22:28:43 +08:00
|
|
|
|
m_dataCenter->startCyclicRead(20);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
2025-08-20 23:06:28 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void P00_PublicPage::UIRefreshTimeOut(){
|
2025-10-10 17:44:10 +08:00
|
|
|
|
|
2025-09-15 22:28:43 +08:00
|
|
|
|
ui->Title->setText(gPageName[gPageIndexStr]);
|
2025-09-28 17:14:34 +08:00
|
|
|
|
// 获取当前时间
|
2025-08-20 23:06:28 +08:00
|
|
|
|
QDateTime currentTime = QDateTime::currentDateTime();
|
|
|
|
|
|
QString currentTimeStr = currentTime.toString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
ui->Lable_SystemTime->setText(currentTimeStr);
|
2025-09-15 22:28:43 +08:00
|
|
|
|
ui->LCD_SystemVal_U1->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_SystemVal.Filtered30_U"].toReal());
|
|
|
|
|
|
ui->LCD_SystemVal_V1->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_SystemVal.Filtered30_V"].toReal());
|
|
|
|
|
|
ui->LCD_SystemVal_W1->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_SystemVal.Filtered30_W"].toReal());
|
|
|
|
|
|
|
|
|
|
|
|
// 修复:使用正确的方式获取节点值并转换为整数
|
|
|
|
|
|
uint16_t AlarmNumber = static_cast<uint16_t>(gOPC_NodeValue["ns=6;s=::AsGlobalPV:AlarmCode.Index"].toUInt());
|
|
|
|
|
|
uint8_t AlarmAllNum = AlarmNumber / 256;
|
|
|
|
|
|
uint8_t AlarmIndex = AlarmNumber % 256;
|
|
|
|
|
|
uint16_t LoopAlarm = static_cast<uint16_t>(gOPC_NodeValue["ns=6;s=::AsGlobalPV:AlarmCode.Loop"].toUInt());
|
|
|
|
|
|
uint8_t LoopAlarm_Dev = LoopAlarm / 256;
|
|
|
|
|
|
uint8_t LoopAlarm_Ind = LoopAlarm % 256;
|
|
|
|
|
|
|
2025-09-30 15:36:46 +08:00
|
|
|
|
uint32_t Bools_4 = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PageBOOLS.B4"].toUInt();
|
|
|
|
|
|
|
2025-09-15 22:28:43 +08:00
|
|
|
|
ui->Txt_AlarmCode->setHidden(AlarmAllNum == 0);
|
|
|
|
|
|
ui->Num_MainAlarmNum->setHidden(AlarmAllNum == 0);
|
|
|
|
|
|
ui->Lable_MainAlarm->setHidden(AlarmAllNum == 0);
|
|
|
|
|
|
ui->Num_MainAlarmNum->setText("共 "+QString::number(AlarmAllNum) + " 条 第 " + QString::number(AlarmIndex)+" 条:");
|
|
|
|
|
|
ui->Txt_AlarmCode->setText("(" + QString("%1").arg(LoopAlarm, 4, 16, QLatin1Char('0')).toUpper() + ")");
|
|
|
|
|
|
|
|
|
|
|
|
// 修复:使用数组边界常量检查代替size()方法
|
|
|
|
|
|
const int MAX_DEV = 255; // 与AlarmText定义匹配
|
|
|
|
|
|
const int MAX_IND = 255; // 与AlarmText定义匹配
|
|
|
|
|
|
|
|
|
|
|
|
if (LoopAlarm_Dev < MAX_DEV && LoopAlarm_Ind < MAX_IND) {
|
|
|
|
|
|
ui->Lable_MainAlarm->setStyleSheet("border-image: url(:/Frames/null.png);\n" + AlarmText[LoopAlarm_Dev][LoopAlarm_Ind].TextColor);
|
|
|
|
|
|
ui->Lable_MainAlarm->setText(AlarmText[LoopAlarm_Dev][LoopAlarm_Ind].AlarmText);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ui->Lable_MainAlarm->setStyleSheet("border-image: url(:/Frames/null.png);");
|
|
|
|
|
|
ui->Lable_MainAlarm->setText("无效报警");
|
|
|
|
|
|
}
|
2025-09-30 15:36:46 +08:00
|
|
|
|
QStringList VoiceList;
|
|
|
|
|
|
VoiceList
|
|
|
|
|
|
<<"油泵电机即将启动\n工作人员请注意!!!"
|
|
|
|
|
|
<<"截割电机即将启动\n工作人员请注意!!!"
|
|
|
|
|
|
<<"收集电机即将启动\n工作人员请注意!!!"
|
|
|
|
|
|
<<"运输电机即将正转\n工作人员请注意!!!"
|
|
|
|
|
|
<<"运输电机即将反转\n工作人员请注意!!!"
|
|
|
|
|
|
<<"备用电机即将启动\n工作人员请注意!!!"
|
|
|
|
|
|
<<"左履带正在前进\n工作人员请注意!!!"
|
|
|
|
|
|
<<"左履带正在后退\n工作人员请注意!!!"
|
|
|
|
|
|
<<"右履带正在前进\n工作人员请注意!!!"
|
|
|
|
|
|
<<"右履带正在后退\n工作人员请注意!!!"
|
|
|
|
|
|
<<"双履带正在前进\n工作人员请注意!!!"
|
|
|
|
|
|
<<"双履带正在后退\n工作人员请注意!!!"
|
|
|
|
|
|
<<"双履带顺时针转向\n工作人员请注意!!!"
|
|
|
|
|
|
<<"双履带逆时针转向\n工作人员请注意!!!"
|
|
|
|
|
|
<<"摇臂正在上升\n工作人员请注意!!!"
|
|
|
|
|
|
<<"摇臂正在下降\n工作人员请注意!!!"
|
|
|
|
|
|
<<"掏槽正在伸出\n工作人员请注意!!!"
|
|
|
|
|
|
<<"掏槽正在缩回\n工作人员请注意!!!";
|
|
|
|
|
|
bool isVoice = false;
|
|
|
|
|
|
for (uint8_t i=0;i<32 && !isVoice;i++) {
|
|
|
|
|
|
if(getBitOf32Data(Bools_4, i,false)){
|
|
|
|
|
|
VoiceWin(VoiceList[i],true);
|
|
|
|
|
|
isVoice = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if(!isVoice) VoiceWin("",false);
|
|
|
|
|
|
|
2025-08-20 23:06:28 +08:00
|
|
|
|
}
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
|
|
|
|
|
// 静态变量初始化
|
|
|
|
|
|
bool P00_PublicPage::OldUp = false;
|
|
|
|
|
|
bool P00_PublicPage::OldDown = false;
|
|
|
|
|
|
bool P00_PublicPage::OldLeft = false;
|
|
|
|
|
|
bool P00_PublicPage::OldRight = false;
|
|
|
|
|
|
bool P00_PublicPage::OldConfirm = false;
|
|
|
|
|
|
|
|
|
|
|
|
void P00_PublicPage::CursorScanTimerOut()
|
|
|
|
|
|
{
|
|
|
|
|
|
uint32_t CursorControl = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PageContol.CursorControl"].toUInt();
|
|
|
|
|
|
bool Up = getBitOf32Data(CursorControl,10);
|
|
|
|
|
|
bool Down = getBitOf32Data(CursorControl,14);
|
|
|
|
|
|
bool Left = getBitOf32Data(CursorControl,13);
|
|
|
|
|
|
bool Right = getBitOf32Data(CursorControl,15);
|
|
|
|
|
|
bool Confirm = getBitOf32Data(CursorControl,11);
|
|
|
|
|
|
bool Return = getBitOf32Data(CursorControl,9);
|
|
|
|
|
|
|
|
|
|
|
|
// 处理按键事件(带防抖)
|
|
|
|
|
|
if(Return) {
|
|
|
|
|
|
gCursor->handleKey(Qt::Key_Enter);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(Up != OldUp) {
|
|
|
|
|
|
gCursor->handleKey(Qt::Key_Up, Up);
|
|
|
|
|
|
OldUp = Up;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(Down != OldDown) {
|
|
|
|
|
|
gCursor->handleKey(Qt::Key_Down, Down);
|
|
|
|
|
|
OldDown = Down;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(Left != OldLeft) {
|
|
|
|
|
|
gCursor->handleKey(Qt::Key_Left, Left);
|
|
|
|
|
|
OldLeft = Left;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(Right != OldRight) {
|
|
|
|
|
|
gCursor->handleKey(Qt::Key_Right, Right);
|
|
|
|
|
|
OldRight = Right;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(!OldConfirm && Confirm) {
|
|
|
|
|
|
gCursor->handleKey(Qt::Key_Return);
|
|
|
|
|
|
OldConfirm = Confirm;
|
|
|
|
|
|
} else if(OldConfirm && !Confirm) {
|
|
|
|
|
|
OldConfirm = false;
|
|
|
|
|
|
}
|
2025-08-20 23:06:28 +08:00
|
|
|
|
}
|
2025-09-15 22:28:43 +08:00
|
|
|
|
|
2025-08-20 23:06:28 +08:00
|
|
|
|
void P00_PublicPage::on_But_Close_clicked()
|
|
|
|
|
|
{
|
|
|
|
|
|
qApp->quit();
|
|
|
|
|
|
}
|
2025-09-15 22:28:43 +08:00
|
|
|
|
// 页面切换实现
|
2025-09-28 17:14:34 +08:00
|
|
|
|
void P00_PublicPage::on_But_Page_0_clicked(){ ChangePage( 0, 1, "P01");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_1_clicked(){ ChangePage( 1, 2, "P02");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_2_clicked(){ ChangePage( 2, 301, "P301");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_3_clicked(){ ChangePage( 3, 401, "P401");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_4_clicked(){ ChangePage( 4, 501, "P501");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_5_clicked(){ ChangePage( 5, 601, "P601");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_6_clicked(){ ChangePage( 6, 7, "P07");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_7_clicked(){ ChangePage( 7, 8, "P08");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_8_clicked(){ ChangePage( 8, 9, "P09");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_9_clicked(){ ChangePage( 9, 10, "P10");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_10_clicked(){ ChangePage(10, 11, "P11");}
|
2025-10-10 17:44:10 +08:00
|
|
|
|
void P00_PublicPage::on_But_Page_11_clicked(){ ChangePage(11, 12, gPageIndexStr12);}
|
2025-09-28 17:14:34 +08:00
|
|
|
|
void P00_PublicPage::on_But_Page_12_clicked(){ ChangePage(12, 13, "P13");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_13_clicked(){ ChangePage(13, 14, "P14");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_14_clicked(){ ChangePage(14, 15, "P15");}
|
|
|
|
|
|
void P00_PublicPage::on_But_Page_15_clicked(){ ChangePage(15, 16, "P16");}
|
|
|
|
|
|
void P00_PublicPage::ChangePage(uint16_t PageIndex,uint16_t PageNum,QString PageName){
|
|
|
|
|
|
smoothScrollTo(PageIndex);
|
|
|
|
|
|
m_opcManager->writeNodeValue("ns=6;s=::AsGlobalPV:PageContol.CurrentPage", PageNum,5,100);
|
|
|
|
|
|
gPageIndexStr = PageName;
|
2025-10-10 17:44:10 +08:00
|
|
|
|
|
2025-09-28 17:14:34 +08:00
|
|
|
|
}
|
2025-09-30 15:36:46 +08:00
|
|
|
|
/* 1. 读写属性 */
|
|
|
|
|
|
QRect P00_PublicPage::voiceGeometry() const
|
|
|
|
|
|
{ return ui->Label_VoiceWidget->geometry(); }
|
|
|
|
|
|
|
|
|
|
|
|
void P00_PublicPage::setVoiceGeometry(const QRect &g)
|
|
|
|
|
|
{ ui->Label_VoiceWidget->setGeometry(g); }
|
|
|
|
|
|
|
|
|
|
|
|
/* 2. 一条动画同时驱动 geometry */
|
|
|
|
|
|
void P00_PublicPage::startGeometryAnim(const QRect &start,
|
|
|
|
|
|
const QRect &end,
|
|
|
|
|
|
int dur)
|
|
|
|
|
|
{
|
|
|
|
|
|
auto *anim = new QPropertyAnimation(this, "voiceGeometry");
|
|
|
|
|
|
anim->setDuration(dur);
|
|
|
|
|
|
anim->setStartValue(start);
|
|
|
|
|
|
anim->setEndValue(end);
|
|
|
|
|
|
anim->setEasingCurve(QEasingCurve::OutQuad);
|
|
|
|
|
|
|
|
|
|
|
|
/* 空组保活,动画结束自动销毁 */
|
|
|
|
|
|
auto *group = new QParallelAnimationGroup(this);
|
|
|
|
|
|
group->addAnimation(anim);
|
|
|
|
|
|
connect(group, &QAbstractAnimation::finished, [this]{
|
|
|
|
|
|
if (voiceGeometry().height() == 0)
|
|
|
|
|
|
ui->Label_VoiceWidget->hide();
|
|
|
|
|
|
});
|
|
|
|
|
|
group->start(QAbstractAnimation::DeleteWhenStopped);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 3. 唯一入口:VoiceWin */
|
|
|
|
|
|
void P00_PublicPage::VoiceWin(const QString &Info, bool shouldShow)
|
|
|
|
|
|
{
|
|
|
|
|
|
ui->Label_VoiceWidget->setText(Info);
|
|
|
|
|
|
if (shouldShow == m_realShow) return;
|
|
|
|
|
|
m_realShow = shouldShow;
|
|
|
|
|
|
|
|
|
|
|
|
const int w = 960;
|
|
|
|
|
|
const int baseY = 70 + 576 / 2; // 中心线
|
|
|
|
|
|
const int x = (1024 - w) / 2;
|
|
|
|
|
|
|
|
|
|
|
|
QRect start = ui->Label_VoiceWidget->geometry();
|
|
|
|
|
|
QRect end;
|
|
|
|
|
|
|
|
|
|
|
|
if (shouldShow) { // 展开
|
|
|
|
|
|
ui->Label_VoiceWidget->show();
|
|
|
|
|
|
int h = 380;
|
|
|
|
|
|
int y = baseY - h / 2;
|
|
|
|
|
|
end = QRect(x, y, w, h);
|
|
|
|
|
|
startGeometryAnim(start, end, 500); // 250 ms 展开
|
|
|
|
|
|
} else { // 收起
|
|
|
|
|
|
int h = 0;
|
|
|
|
|
|
int y = baseY - h / 2;
|
|
|
|
|
|
end = QRect(x, y, w, h);
|
|
|
|
|
|
startGeometryAnim(start, end, 100); // 80 ms 快速收起
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|