Files
EJM_Display/Pages/P10_IntelligentPage.cpp

247 lines
8.8 KiB
C++
Raw Normal View History

2025-08-20 23:06:28 +08:00
#include "P10_IntelligentPage.h"
#include "ui_P10_IntelligentPage.h"
2025-09-15 22:28:43 +08:00
#include <QScrollArea>
#include <QScrollBar>
#include <QDebug>
#include <QString>
2025-08-20 23:06:28 +08:00
2025-09-15 22:28:43 +08:00
// 构造函数初始化UI与播放器
2025-08-20 23:06:28 +08:00
P10_IntelligentPage::P10_IntelligentPage(QWidget *parent) :
QWidget(parent),
2025-09-28 17:14:34 +08:00
ui(new Ui::P10_IntelligentPage)
2025-08-20 23:06:28 +08:00
{
ui->setupUi(this);
2025-09-28 17:14:34 +08:00
#if CONFIG_EN_RTSP //开启 RTSP 读取
m_rtspPlayer = new RtspPlayer(this);// 初始化RTSP播放器父对象绑定避免内存泄漏
2025-10-20 22:28:37 +08:00
QTimer::singleShot(1000, this, &P10_IntelligentPage::WinInit); // 调用初始化函数
2025-09-28 17:14:34 +08:00
#endif
2025-08-20 23:06:28 +08:00
}
2025-09-15 22:28:43 +08:00
// 析构函数:释放资源
2025-08-20 23:06:28 +08:00
P10_IntelligentPage::~P10_IntelligentPage()
{
2025-09-28 17:14:34 +08:00
#if CONFIG_EN_RTSP //开启 RTSP 读取
2025-09-15 22:28:43 +08:00
// 停止RTSP播放并释放播放器资源
if (m_rtspPlayer != nullptr) {
m_rtspPlayer->stopPlay();
m_rtspPlayer->wait(); // 等待播放线程完全退出,避免资源冲突
}
2025-09-28 17:14:34 +08:00
#endif
2025-09-15 22:28:43 +08:00
delete ui; // 释放UI对象
}
2025-09-28 17:14:34 +08:00
#if CONFIG_EN_RTSP //开启 RTSP 读取
2025-09-15 22:28:43 +08:00
// 界面与逻辑初始化
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确保资源释放
2025-10-14 20:05:38 +08:00
m_rtspUrl = RTSP_Url;
2025-09-15 22:28:43 +08:00
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)
{
2025-10-10 17:44:10 +08:00
if(gPageIndexStr != "P10")
return;
2025-09-15 22:28:43 +08:00
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; // 其他事件不拦截,正常传递
}
2025-08-20 23:06:28 +08:00
}
2025-09-28 17:14:34 +08:00
#endif