#include "weighui.h" #include "./ui_weighui.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dds/Subscriber.hpp" #include "dds/msg.hpp" // DdsMsgData 静态成员定义 std::queue DdsMsgData::SummaryUpdate_queue_; std::queue DdsMsgData::QueueSuccess_queue_; std::mutex DdsMsgData::queue_cv_mtx_; WeighUI::WeighUI(int domainId, QWidget *parent) : QMainWindow(parent) , ui(new Ui::WeighUI) , m_imageLabel(nullptr) , m_popupWidget(nullptr) , m_ddsSubscriber(nullptr) , m_ddsThread(nullptr) , m_domainId(domainId) { qDebug() << "=== WeighUI 构造函数开始 ==="; ui->setupUi(this); qDebug() << "setupUi 完成, 窗口大小:" << width() << "x" << height(); this->setAttribute(Qt::WA_DeleteOnClose); // 设置窗口为全屏无边框(适应 800x1280 竖屏) this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint); this->resize(800, 1280); this->showFullScreen(); this->raise(); this->activateWindow(); qDebug() << "窗口大小已调整为:" << width() << "x" << height(); // 隐藏菜单栏和状态栏 ui->menubar->hide(); ui->statusbar->hide(); // 设置 centralwidget 透明并隐藏 ui->centralwidget->setStyleSheet("background-color: transparent;"); ui->centralwidget->hide(); // 创建图片显示Label m_imageLabel = new QLabel(this); m_imageLabel->setAlignment(Qt::AlignCenter); m_imageLabel->setScaledContents(true); m_imageLabel->setGeometry(0, 0, width(), height()); m_imageLabel->show(); // 加载图片并旋转90度 QString imagePath = QCoreApplication::applicationDirPath() + "/123.png"; qDebug() << "尝试加载图片:" << imagePath; QPixmap pixmap(imagePath); if (!pixmap.isNull()) { QTransform transform; transform.rotate(90); QPixmap rotatedPixmap = pixmap.transformed(transform); m_imageLabel->setPixmap(rotatedPixmap.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); qDebug() << "图片加载并旋转成功!"; } else { qDebug() << "图片加载失败!"; } // 创建定时器 m_closeTimer = new QTimer(this); m_pollTimer = new QTimer(this); m_summaryPollTimer = new QTimer(this); connect(m_closeTimer, &QTimer::timeout, this, &WeighUI::onPopupClosed); connect(m_pollTimer, &QTimer::timeout, this, &WeighUI::onCheckQueueSuccess); connect(m_summaryPollTimer, &QTimer::timeout, this, &WeighUI::onCheckSummaryUpdate); // 排队成功提示音(sound1.wav)在 onCheckQueueSuccess 中由 aplay 子进程播放 // 启动 DDS 订阅 SummaryUpdate / QueueSuccess startDdsSubscriber(); // 启动轮询定时器(每 200ms 检查队列) m_pollTimer->start(200); m_summaryPollTimer->start(200); qDebug() << "=== WeighUI 构造函数结束(等待 QueueSuccess 触发弹窗)==="; } WeighUI::~WeighUI() { stopDdsSubscriber(); delete ui; } void WeighUI::startDdsSubscriber() { try { qDebug() << "DDS Subscriber 启动, domainId=" << m_domainId; m_ddsSubscriber = std::make_shared(m_domainId); m_ddsThread = new std::thread([this]() { m_ddsSubscriber->run(); }); qDebug() << "DDS Subscriber 启动成功"; } catch (const std::exception& e) { qDebug() << "DDS Subscriber 启动失败:" << e.what(); m_ddsSubscriber = nullptr; m_ddsThread = nullptr; } } void WeighUI::stopDdsSubscriber() { if (m_ddsSubscriber) { m_ddsSubscriber->stop(); } if (m_ddsThread) { if (m_ddsThread->joinable()) { m_ddsThread->join(); } delete m_ddsThread; m_ddsThread = nullptr; } m_ddsSubscriber.reset(); } void WeighUI::closeEvent(QCloseEvent *event) { stopDdsSubscriber(); if (m_pollTimer) m_pollTimer->stop(); if (m_summaryPollTimer) m_summaryPollTimer->stop(); if (m_closeTimer) m_closeTimer->stop(); hide(); QTimer::singleShot(100, [this]() { deleteLater(); }); event->accept(); } void WeighUI::onCheckSummaryUpdate() { // SummaryUpdate 目前不触发任何 UI 动作,仅消费队列避免消息堆积 std::unique_lock lock(DdsMsgData::queue_cv_mtx_); while (!DdsMsgData::SummaryUpdate_queue_.empty()) { DdsMsgData::SummaryUpdate_queue_.pop(); } } void WeighUI::onCheckQueueSuccess() { QString popupText; bool hasData = false; { std::unique_lock lock(DdsMsgData::queue_cv_mtx_); if (!DdsMsgData::QueueSuccess_queue_.empty()) { Queue::QueueSuccess info = std::move(DdsMsgData::QueueSuccess_queue_.front()); DdsMsgData::QueueSuccess_queue_.pop(); lock.unlock(); popupText = QString::fromStdString(info.display_text()); if (popupText.isEmpty()) { popupText = QStringLiteral("排队成功"); } hasData = true; qDebug() << "[WeighUI] 收到 QueueSuccess, display_text =" << popupText; } } if (hasData) { // 播放提示音:启动 aplay 子进程异步播放,父进程立即返回不阻塞 Qt 事件循环 // 用 QProcess::startDetached 起一个干净的短进程,完全绕开 QSoundEffect QString soundPath = QCoreApplication::applicationDirPath() + "/voice2.0/sound1.wav"; QProcess::startDetached("aplay", QStringList() << "-q" << soundPath); onShowPopup(popupText); } } void WeighUI::onShowPopup(const QString& popupText) { if (m_popupWidget) { m_popupWidget->close(); m_popupWidget->deleteLater(); m_popupWidget = nullptr; } // 创建弹窗容器(横屏尺寸:宽800,高500) QWidget *popupSource = new QWidget(this); popupSource->setWindowFlags(Qt::FramelessWindowHint | Qt::Window); popupSource->resize(800, 500); // 内部布局:上方标题 + 下方信息(QueueSuccess.display_text) QVBoxLayout *mainLayout = new QVBoxLayout(popupSource); mainLayout->setContentsMargins(20, 20, 20, 20); mainLayout->setSpacing(20); mainLayout->setAlignment(Qt::AlignCenter); // 上方:标题 QLabel *titleLabel = new QLabel("排队提示", popupSource); titleLabel->setAlignment(Qt::AlignCenter); titleLabel->setStyleSheet("font-size: 48px; font-weight: bold; color: #4169E1; background: transparent;"); QFrame *line = new QFrame(popupSource); line->setFrameShape(QFrame::HLine); line->setStyleSheet("background-color: #4169E1;"); // 下方:信息(QueueSuccess.display_text 文本) QLabel *warningLabel = new QLabel(popupText, popupSource); warningLabel->setAlignment(Qt::AlignCenter); warningLabel->setWordWrap(true); warningLabel->setStyleSheet("font-size: 42px; font-weight: bold; color: #FF4500; background: transparent;"); mainLayout->addWidget(titleLabel); mainLayout->addWidget(line); mainLayout->addWidget(warningLabel); // 把弹窗渲染成图片 popupSource->show(); popupSource->repaint(); QPixmap popupPixmap = popupSource->grab(); // 关闭原弹窗 popupSource->close(); popupSource->deleteLater(); // 旋转90度,跟图片一致 QTransform transform; transform.rotate(90); QPixmap rotatedPixmap = popupPixmap.transformed(transform, Qt::SmoothTransformation); // 创建新弹窗显示旋转后的图片 m_popupWidget = new QWidget(this); m_popupWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Window); m_popupWidget->setStyleSheet( "background-color: rgba(240, 248, 255, 240);" "border: 3px solid #4169E1;" "border-radius: 15px;" ); m_popupWidget->resize(rotatedPixmap.width(), rotatedPixmap.height()); QLabel *imageLabel = new QLabel(m_popupWidget); imageLabel->setPixmap(rotatedPixmap); imageLabel->setScaledContents(true); imageLabel->setGeometry(0, 0, rotatedPixmap.width(), rotatedPixmap.height()); m_popupWidget->move((width() - rotatedPixmap.width()) / 2, (height() - rotatedPixmap.height()) / 2); m_popupWidget->show(); // 5秒后关闭弹窗 m_closeTimer->setSingleShot(true); m_closeTimer->start(5000); } void WeighUI::onPopupClosed() { if (m_popupWidget) { m_popupWidget->close(); m_popupWidget->deleteLater(); m_popupWidget = nullptr; } }