|
|
#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;
|
|
|
}
|
|
|
}
|