Files
EJM_Display/Pages/P10_IntelligentPage.cpp
2025-10-21 11:11:52 +08:00

247 lines
8.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "P10_IntelligentPage.h"
#include "ui_P10_IntelligentPage.h"
#include <QScrollArea>
#include <QScrollBar>
#include <QDebug>
#include <QString>
// 构造函数初始化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播放器父对象绑定避免内存泄漏
QTimer::singleShot(1000, this, &P10_IntelligentPage::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_Url;
QTimer::singleShot(800, this, [=]() {
ui->videoLabel->setText("正在连接实物图摄像头...");
if (m_rtspPlayer->init(m_rtspUrl)) {
m_rtspPlayer->startPlay();
} else {
ui->videoLabel->setText("摄像头1连接失败\n请检查地址/网络");
}
});
}
// 切换到摄像头2RTSP地址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<QMouseEvent*>(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<QMouseEvent*>(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<QMouseEvent*>(ev);
if (dragging && mouseEv->button() == Qt::LeftButton) {
dragging = false;
ui->videoLabel->unsetCursor(); // 恢复默认鼠标样式
}
return true;
}
default:
return false; // 其他事件不拦截,正常传递
}
}
#endif