#include "P10_IntelligentPage.h" #include "ui_P10_IntelligentPage.h" #include #include #include #include // 构造函数:初始化UI与播放器 P10_IntelligentPage::P10_IntelligentPage(QWidget *parent) : QWidget(parent), ui(new Ui::P10_IntelligentPage) { ui->setupUi(this); #if CONFIG_EN_RTSP //开启 RTSP 读取 m_rtspPlayer = new RtspPlayer(this);// 初始化RTSP播放器(父对象绑定,避免内存泄漏) WinInit(); // 调用初始化函数 #endif } // 析构函数:释放资源 P10_IntelligentPage::~P10_IntelligentPage() { #if CONFIG_EN_RTSP //开启 RTSP 读取 // 停止RTSP播放并释放播放器资源 if (m_rtspPlayer != nullptr) { m_rtspPlayer->stopPlay(); m_rtspPlayer->wait(); // 等待播放线程完全退出,避免资源冲突 } #endif delete ui; // 释放UI对象 } #if CONFIG_EN_RTSP //开启 RTSP 读取 // 界面与逻辑初始化 void P10_IntelligentPage::WinInit() { // 配置视频显示区域(绑定到ScrollArea,支持缩放后滚动) ui->videoLabel->setParent(nullptr); // 解除原有父控件绑定 ui->scrollArea->setWidget(ui->videoLabel); // 将videoLabel设为ScrollArea的内容控件 ui->scrollArea->setWidgetResizable(false); // 禁用自动调整大小(手动控制缩放) ui->videoLabel->installEventFilter(this); // 为videoLabel安装事件过滤器(处理拖拽) ui->videoLabel->setAlignment(Qt::AlignCenter); // 视频帧居中显示 ui->Label_Zoom->setText("100 %"); // 初始化缩放比例显示(补充百分号,更直观) // 连接RTSP播放器信号槽(帧接收、错误提示) connect(m_rtspPlayer, &RtspPlayer::frameReady, this, &P10_IntelligentPage::onFrameReady); connect(m_rtspPlayer, &RtspPlayer::errorOccurred, this, &P10_IntelligentPage::onErrorOccurred); // 默认加载第一个摄像头 on_But_Atlas_1_clicked(); } // 设置RTSP地址(外部调用接口,可选) void P10_IntelligentPage::setRtspUrl(const QString &url) { m_rtspUrl = url; } void P10_IntelligentPage::on_But_Atlas_1_clicked() { // 1. 强制停止播放并等待线程退出(关键) m_rtspPlayer->stopPlay(); if (m_rtspPlayer->isRunning()) { ui->videoLabel->setText("正在释放资源..."); if (!m_rtspPlayer->wait(1000)) { // 最多等待1秒 qWarning() << "旧线程未正常退出,强制终止"; } } // 2. 重置参数(同之前逻辑) Img_Zoom = 1.0f; Img_W = 900; Img_H = 576; ui->scrollArea->resize(Img_W, Img_H); ui->videoLabel->resize(Img_W, Img_H); ui->videoLabel->setAlignment(Qt::AlignCenter); ui->Label_Zoom->setText("100 %"); ui->But_Atlas_3->setText("暂停"); // 3. 延迟初始化新流(延长延迟到800ms,确保资源释放) m_rtspUrl = "rtsp://admin:sshw1212@192.168.1.64:554/Streaming/Channels/101"; QTimer::singleShot(800, this, [=]() { ui->videoLabel->setText("正在连接实物图摄像头..."); if (m_rtspPlayer->init(m_rtspUrl)) { m_rtspPlayer->startPlay(); } else { ui->videoLabel->setText("摄像头1连接失败\n请检查地址/网络"); } }); } // 切换到摄像头2(RTSP地址2) void P10_IntelligentPage::on_But_Atlas_2_clicked() { // 1. 强制停止播放并等待线程退出(关键) m_rtspPlayer->stopPlay(); if (m_rtspPlayer->isRunning()) { ui->videoLabel->setText("正在释放资源..."); if (!m_rtspPlayer->wait(1000)) { // 最多等待1秒 qWarning() << "旧线程未正常退出,强制终止"; } } // 2. 重置参数(同之前逻辑) Img_Zoom = 1.0f; Img_W = 800; Img_H = 576; ui->scrollArea->resize(Img_W, Img_H); ui->videoLabel->resize(Img_W, Img_H); ui->Label_Zoom->setText("100 %"); ui->But_Atlas_3->setText("暂停"); // 3. 设置摄像头2的RTSP地址并延迟初始化 m_rtspUrl = "rtsp://admin:sshw1212@192.168.1.64:554/Streaming/Channels/201"; QTimer::singleShot(800, this, [=]() { ui->videoLabel->setText("正在连接热力图摄像头..."); if (m_rtspPlayer->init(m_rtspUrl)) { m_rtspPlayer->startPlay(); } else { ui->videoLabel->setText("摄像头1连接失败\n请检查地址/网络"); } }); } // 暂停/继续播放(切换按钮文本与播放状态) void P10_IntelligentPage::on_But_Atlas_3_clicked() { // 检查播放器是否已初始化(避免空操作) if (!m_rtspPlayer->isRunning()) { ui->videoLabel->setText("未连接摄像头\n无法操作"); return; } if (ui->But_Atlas_3->text() == "继续") { ui->But_Atlas_3->setText("暂停"); m_rtspPlayer->startPlay(); // 继续播放 } else { ui->But_Atlas_3->setText("继续"); m_rtspPlayer->pausePlay(); // 暂停播放 } } // 图像放大(步长0.1,最大5倍) void P10_IntelligentPage::on_But_Magnify_clicked() { if (Img_Zoom >= 5.0f) return; // 限制最大缩放比例 Img_Zoom += 0.1f; // 格式化缩放比例显示(保留2位小数,加百分号) ui->Label_Zoom->setText(QString::asprintf("%.0f %%", Img_Zoom * 100)); // 计算并调整视频Label大小(用qRound避免浮点数精度问题) int newW = qRound(Img_W * Img_Zoom); int newH = qRound(Img_H * Img_Zoom); ui->videoLabel->resize(newW, newH); } // 图像缩小(步长0.1,最小1倍) void P10_IntelligentPage::on_But_Reduce_clicked() { if (Img_Zoom <= 1.0f) return; // 限制最小缩放比例(不小于原始尺寸) Img_Zoom -= 0.1f; ui->Label_Zoom->setText(QString::asprintf("%.0f %%", Img_Zoom * 100)); int newW = qRound(Img_W * Img_Zoom); int newH = qRound(Img_H * Img_Zoom); ui->videoLabel->resize(newW, newH); } // 接收新视频帧,转换为QPixmap并显示 void P10_IntelligentPage::onFrameReady(const QImage &frame) { if(gPageIndexStr != "P10") return; if (frame.isNull()) return; // 过滤空帧,避免无效操作 // 缩放帧图像(保持宽高比,填充Label,平滑缩放) QPixmap pixmap = QPixmap::fromImage(frame).scaled( ui->videoLabel->size(), Qt::KeepAspectRatioByExpanding, // 按比例填充Label(不拉伸变形) Qt::SmoothTransformation // 平滑缩放,提升画质 ); ui->videoLabel->setPixmap(pixmap); } // 接收错误信息,显示到视频Label并打印调试日志 void P10_IntelligentPage::onErrorOccurred(const QString &msg) { qDebug() << "[P10_IntelligentPage 摄像头错误]:" << msg; // 在视频区域显示错误信息(换行优化显示) ui->videoLabel->setText(QString("错误:\n%1").arg(msg)); ui->videoLabel->setPixmap(QPixmap()); // 清除当前显示的图像 } // 事件过滤器:处理videoLabel的鼠标拖拽平移 bool P10_IntelligentPage::eventFilter(QObject *obj, QEvent *ev) { // 仅处理videoLabel的事件,且确保有图像显示时才响应拖拽 if (obj != ui->videoLabel || !ui->videoLabel->pixmap()) { return false; } switch (ev->type()) { case QEvent::MouseButtonPress: { QMouseEvent *mouseEv = static_cast(ev); // 仅响应左键按下 if (mouseEv->button() == Qt::LeftButton) { dragging = true; dragStart = mouseEv->pos(); // 记录拖拽起始点 ui->videoLabel->setCursor(Qt::ClosedHandCursor); // 改变鼠标样式(闭合手) } return true; // 拦截事件,避免向下传递 } case QEvent::MouseMove: { if (!dragging) return false; // 未处于拖拽状态,不处理 QMouseEvent *mouseEv = static_cast(ev); // 计算拖拽偏移量 int dx = mouseEv->pos().x() - dragStart.x(); int dy = mouseEv->pos().y() - dragStart.y(); // 调整ScrollArea的滚动条位置(实现平移) QScrollBar *hBar = ui->scrollArea->horizontalScrollBar(); QScrollBar *vBar = ui->scrollArea->verticalScrollBar(); hBar->setValue(qBound(hBar->minimum(), hBar->value() - dx, hBar->maximum())); vBar->setValue(qBound(vBar->minimum(), vBar->value() - dy, vBar->maximum())); dragStart = mouseEv->pos(); // 更新起始点,准备下一次计算 return true; } case QEvent::MouseButtonRelease: { QMouseEvent *mouseEv = static_cast(ev); if (dragging && mouseEv->button() == Qt::LeftButton) { dragging = false; ui->videoLabel->unsetCursor(); // 恢复默认鼠标样式 } return true; } default: return false; // 其他事件不拦截,正常传递 } } #endif