You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
8.6 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "weighui.h"
#include "./ui_weighui.h"
#include <QTimer>
#include <QPixmap>
#include <QDebug>
#include <QCloseEvent>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTransform>
#include <QLabel>
#include <QFrame>
#include <thread>
#include <mutex>
#include <queue>
#include <utility>
#include <QProcess>
#include "dds/Subscriber.hpp"
#include "dds/msg.hpp"
// DdsMsgData 静态成员定义
std::queue<WeighingSystem::SummaryUpdate> DdsMsgData::SummaryUpdate_queue_;
std::queue<Queue::QueueSuccess> 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<DdsSubscriberApp>(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<std::mutex> 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<std::mutex> 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;
}
}