1 介绍
2 细节
2.1 执行程序只能唯一执行
使用QShareMemory创建共享内存
2.2 类声明代替头文件
- 若头文件中没有创建某个类的对象,可以不写 #include <类名>,使用class 类名 代替,节省编译时间,不用整个头文件的内容插入过来。
- 对应的源文件需要包含对应的头文件
2.3 单例模式(Singleton)
- 保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
- IconHelper类使用该模式
2.4 qApp 全局对象
A global pointer referring to the unique application object. It is equivalent to QCoreApplication::instance(), but cast as a QApplication pointer, so only valid when the unique application object is a QApplication.
2.4.1 用法
- int main(int argc, char * argv[])
用法:aApp->arg(0)—>这样就能获取,其运行时的当前的目录了,可以方便找到统一附带的xml文件 - connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
使用信号与槽直接退出应用程序
2.5 鼠标事件
2.5.1 介绍
- 单击界面上的按钮,那么就会产生鼠标事件QMouseEvent(不是按钮产生的),由于按钮被按下了,所以他会发出一个单击信号clicked()信号(是按钮产生的),这里只考虑单击信号而不用考虑鼠标事件,但如果要设计一个按钮,或者当单击按钮时让它产生别的效果,此时就要考虑鼠标事件了,由此,信号和事件是两个不同层面的东西,发出者不同,作用不同。Qt中,所有的QObject的子类实例均可对事件接收和处理!
- Qt学习之路之鼠标事件
- Qt 中的事件处理
- Qt ------ 覆盖eventFilter(),捕获组件事件,事件处理
- qt事件传递过程和处理–朝问道
2.5.2 eventFilter()事件过滤器
- QT将事件封装为QEvent实例以后,会呼叫QObject的event()方法,并且将QEvent实例传送给它,在某些情况下,希望在执行event()之前,先对一些事件进行处理或过滤,然后再决定是否呼叫event()方法,这时候可以使用事件过滤器。
- 在Qt中,当一个事件发生时(例如鼠标点击或某个键盘上的按键按下),其传递顺序如图所示
2.5.2.1 事件过滤器由QObject类中的两个函数来实现
- 一是 installEventFilter函数,它负责在相应部件上安装事件过滤器,其声明为:
void QObject::installEventFilter(QObject *filterObj);
其中,filterObj参数表示要在其上实现事件过滤器函数的部件。请注意,如果我们在一个部件安装了事件过滤器,一般在其父控件上实现事件过滤器函数。 - 二是 eventFilter 函数,我们在此函数中实现事件过滤器。请注意:该函数在 QObject 类中声明为一个虚函数,因此只能由 QObject 的子类继承使用
2.5.2.2 代码实现
bool FilterObject::eventFilter(QObject *object, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Tab)
{
// 处理Tab键
return true;
}
}
return false;
}
/* eventFilter()的object参数表示事件发生的来源物件,eventFilter()若返回false,
则安装该事件过滤器的对象的event()会继续执行,若返回true,
则安装事件过滤器的对象后event()方法就不会被执行,由此进行事件的拦截处理。 */
/* 给本对象安装事件过滤器 */
this->installEventFilter(this);
2.6 信号与槽
- QPushButton使用代码实现,信号与槽实现相应功能
- Qt: qobject_cast(sender()) 简化信号与槽的编写
2.7 全屏与正常模式转换
- 界面对应三个模块:wg_title、wg_main、tw_main,通道label全部继承wg_main,全屏时直接隐藏wg_title和tw_main,wg_main直接放大,正常模式显示wg_title和tw_main,wg_main大小重置
2.8 通道变化
- 双击label,全屏,Esc退出,此处鼠标事件过滤器函数和键盘事件过滤器函数实现
- 右击显示menu,选择切换选项,然后显示。
使用QHBoxLayout创建4个对象,hl_video1,hl_video2,hl_video3,hl_video4
16通道时,使用4个对象分别add4个label;
9通道时,使用3个对象分别add3个label;
4通道时,使用2个对象分别add2个label;
1通道时,使用1个对象直接add1个label;
使用QVBoxLayout创建vl_video,然后vl_video->addLayout(hl_video1),wg_main->setLayout(vl_video) - 注意栅格化
2.9 应用界面
2.9.1 主界面尺寸同屏幕
this->setGeometry(qApp->desktop()->availableGeometry()); //有效尺寸,不含任务栏
this->layout()->setContentsMargins(1, 1, 1, 1); //避免初始化出现右边缘遮住
2.9.2 video部分和treeWidget同高低
- 代码构造部件时,继承关系类似,都先放置部件载体widget,然后addLayout函数加载QVBoxLayout,QVBoxLayout中再add部件,最终部件同高
2.10 单通道放大(类型识别)
鼠标事件过滤器函数eventFilter()中判断
- 双击
event->type() == QEvent::MouseButtonDblClick
MouseEvent->buttons() == Qt::LeftButton)- 类型识别确定是label
QLabel *label = qobject_cast<QLabel *>(obj)
2.10.1 双击放大
对应label直接放大
2.10.2 双击返回
使用类MyApp中的静态成员变量,来重置放大前的界面
static QString VideoType; //当前画面展示类型
2.11 图像一直变大
策略设置为Ignored
QSizePolicy sp_main = wg_main->sizePolicy();
sp_main.setHorizontalPolicy(QSizePolicy::Ignored);
sp_main.setVerticalPolicy(QSizePolicy::Ignored);
wg_main->setSizePolicy(sp_main);
3 代码
- frmmain.h
#ifndef FRMMAIN_H
#define FRMMAIN_H
#include <QDialog>
#include <QList>
#include "video.h"
//下面没有用到类的对象,直接声明该类,节省编译时间
//源文件需要包含对应的头文件
class QMenu;
class QLabel;
class QWidget;
class QModelIndex;
class QTreeWidget;
class QPushButton;
class QHBoxLayout;
class QVBoxLayout;
class MyApp;
class QTimer;
namespace Ui {
class FrmMain;
}
class FrmMain : public QDialog
{
Q_OBJECT
public:
explicit FrmMain(QWidget *parent = 0);
~FrmMain();
protected:
//实现最小化、关闭
bool eventFilter(QObject *obj, QEvent *event); //事件重写
void keyPressEvent(QKeyEvent *event);
protected slots:
void VideoDisplay();
void ChangeStyle(); //切换样式
void ScreenFull(); //全屏模式,隐藏title和treeWidget,通道界面放大
void ScreenNormal(); //普通模式,显示title和treeWidget,通道界面重置
void DeleteVideoOne(); //删除当前视频
void DeleteVideoAll(); //删除所有视频
void SnapshotVideoOne(); //截图当前视频
void SnapshotVideoAll(); //截图所有视频
void ShowVideo1(); //切换到1画面
void ShowVideo4(); //切换到4画面
void ShowVideo9(); //切换到9画面
void ShowVideo16(); //切换到16画面
private:
Ui::FrmMain *ui;
QTimer *timer;
Video *videoTmp;
QMenu *menu; //鼠标右键菜单对象
QMenu *menuStyle; //样式表
bool videoMax; //通道是否处于最大化
QList<QLabel *> videoLab; //通道显示视频label载体
QList<QLayout *> videoLay; //通道视频所在label的layout
void InitStyle(); //初始化无边框窗体
void InitElement(); //初始化部件
void InitForm(); //初始化菜单栏窗体数据:安装事件过滤器
void InitVideo(); //初始化视频布局载体数据
void LoadVideo(); //加载配置数据
void LoadNVRIPC(); //加载NVR及IPC数据
void RemoveLayout(); //移除所有布局
void ChangeVideo1(int index); //改变1画面布局
void ChangeVideo4(int index); //改变4画面布局
void ChangeVideo9(int index); //改变9画面布局
void ChangeVideo16(int index); //改变16画面布局
void ChangeVideoLayout(); //改变通道布局
//构建上面部分:1个widget、11个label、2个pushButton,未初始化
QWidget *wg_up = NULL; //部件载体
QLabel *lb_ico = NULL; //图标
QLabel *lb_title = NULL; //工程名
QLabel *lb_full = NULL; //全屏
QLabel *lb_start = NULL; //启动轮询
QLabel *lb_NVR = NULL; //NVR管理
QLabel *lb_IPC = NULL; //IPC管理
QLabel *lb_pollConfig = NULL; //轮询设置
QLabel *lb_videoPlayBack = NULL;//视频回放
QLabel *lb_config = NULL; //系统设置
QLabel *lb_exit = NULL; //退出系统
QLabel *lb_style = NULL; //样式
QPushButton *pb_min = NULL; //最小化
QPushButton *pb_close = NULL; //关闭
//构建QTreeWidget,未初始化
QWidget *wg_tree = NULL; //部件载体
QVBoxLayout *vl_tree = NULL; //与video部件构造一致,保持界面同一水平线
QTreeWidget *tw_treeMain = NULL;
//构建主要部分:1个treeWidget、1个widget、16个label,未初始化
QWidget *wg_main = NULL; //部件载体
QLabel *lb_video1 = NULL;
QLabel *lb_video2 = NULL;
QLabel *lb_video3 = NULL;
QLabel *lb_video4 = NULL;
QLabel *lb_video5 = NULL;
QLabel *lb_video6 = NULL;
QLabel *lb_video7 = NULL;
QLabel *lb_video8 = NULL;
QLabel *lb_video9 = NULL;
QLabel *lb_video10 = NULL;
QLabel *lb_video11 = NULL;
QLabel *lb_video12 = NULL;
QLabel *lb_video13 = NULL;
QLabel *lb_video14 = NULL;
QLabel *lb_video15 = NULL;
QLabel *lb_video16 = NULL;
//构建水平裂变器,未初始化
QVBoxLayout *vl_video = NULL;
QHBoxLayout *hl_video1 = NULL;
QHBoxLayout *hl_video2 = NULL;
QHBoxLayout *hl_video3 = NULL;
QHBoxLayout *hl_video4 = NULL;
};
#endif // FRMMAIN_H
- frmmain.cpp
#include "frmmain.h"
#include "ui_frmmain.h"
#include "iconhelper.h"
#include "myapp.h"
#include <QKeyEvent>
#include <QMenu>
#include <QFont>
#include <QPalette>
#include <QPixmap>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTimer>
FrmMain::FrmMain(QWidget *parent) :
QDialog(parent),
ui(new Ui::FrmMain)
{
ui->setupUi(this);
this->InitStyle();
this->InitElement();
this->InitForm();
videoTmp = new Video;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(VideoDisplay()));
timer->start(33);
}
FrmMain::~FrmMain()
{
delete ui;
}
void FrmMain::VideoDisplay()
{
if (!videoTmp->cap.isOpened())
{
videoTmp->open_video(0);
}
if (videoTmp->readFrame(lb_video1).isNull())
{
videoTmp->open_video(0);
}
lb_video1->setPixmap(QPixmap::fromImage(videoTmp->readFrame(lb_video1)));
lb_video1->setAlignment(Qt::AlignCenter);
}
//构建主界面部件
void FrmMain::InitElement()
{
//设置字号
QFont ft;
ft.setPointSize(11);
//设置颜色
QPalette pa;
pa.setColor(QPalette::WindowText,Qt::black);
//设置StyleSheet
QString stytleStr = "border: 1px black white;";
//主界面尺寸同屏幕
this->setGeometry(qApp->desktop()->availableGeometry());
this->layout()->setContentsMargins(1, 1, 1, 1);
//构建上面部分:1个widget、11个label、2个pushButton,初始化
//部件载体
wg_up = new QWidget(ui->wg_whole);
wg_up->resize(MyApp::DeskWidth, MyApp::DeskHeight / 37);
wg_up->move(0, 0);
//图标
lb_ico = new QLabel(wg_up);
lb_ico->resize(MyApp::DeskWidth / 46, MyApp::DeskHeight / 40);
lb_ico->move(0, 0);
QPixmap pixmap(":/image/sen.jpg");
lb_ico->setPixmap(pixmap);
lb_ico->setScaledContents(true);
//工程名
lb_title = new QLabel(wg_up);
lb_title->setText(tr("视频监控平台"));
lb_title->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
lb_title->setStyleSheet(stytleStr);
lb_title->setFont(ft);
lb_title->setPalette(pa);
lb_title->resize((MyApp::DeskWidth * 5) / 17, MyApp::DeskHeight / 37);
lb_title->move(MyApp::DeskWidth / 38, 0);
//全屏
lb_full = new QLabel(wg_up);
lb_full->setText(tr("进入全屏"));
lb_full->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_full->setStyleSheet(stytleStr);
lb_full->setFont(ft);
lb_full->setPalette(pa);
lb_full->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_full->move((MyApp::DeskWidth * 19) / 30, 0);
//启动轮询
lb_start = new QLabel(wg_up);
lb_start->setText(tr("启动轮询"));
lb_start->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_start->setStyleSheet(stytleStr);
lb_start->setFont(ft);
lb_start->setPalette(pa);
lb_start->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_start->move((MyApp::DeskWidth * 20) / 30, 0);
//NVR管理
lb_NVR = new QLabel(wg_up);
lb_NVR->setText(tr("NVR管理"));
lb_NVR->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_NVR->setStyleSheet(stytleStr);
lb_NVR->setFont(ft);
lb_NVR->setPalette(pa);
lb_NVR->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_NVR->move((MyApp::DeskWidth * 21) / 30, 0);
//IPC管理
lb_IPC = new QLabel(wg_up);
lb_IPC->setText(tr("IPC管理"));
lb_IPC->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_IPC->setStyleSheet(stytleStr);
lb_IPC->setFont(ft);
lb_IPC->setPalette(pa);
lb_IPC->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_IPC->move((MyApp::DeskWidth * 22) / 30, 0);
//轮询设置
lb_pollConfig = new QLabel(wg_up);
lb_pollConfig->setText(tr("轮询设置"));
lb_pollConfig->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_pollConfig->setStyleSheet(stytleStr);
lb_pollConfig->setFont(ft);
lb_pollConfig->setPalette(pa);
lb_pollConfig->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_pollConfig->move((MyApp::DeskWidth * 23) / 30, 0);
//视频回放
lb_videoPlayBack = new QLabel(wg_up);
lb_videoPlayBack->setText(tr("视频回放"));
lb_videoPlayBack->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_videoPlayBack->setStyleSheet(stytleStr);
lb_videoPlayBack->setFont(ft);
lb_videoPlayBack->setPalette(pa);
lb_videoPlayBack->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_videoPlayBack->move((MyApp::DeskWidth * 24) / 30, 0);
//系统设置
lb_config = new QLabel(wg_up);
lb_config->setText(tr("系统设置"));
lb_config->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_config->setStyleSheet(stytleStr);
lb_config->setFont(ft);
lb_config->setPalette(pa);
lb_config->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_config->move((MyApp::DeskWidth * 25) / 30, 0);
//退出系统
lb_exit = new QLabel(wg_up);
lb_exit->setText(tr("退出系统"));
lb_exit->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_exit->setStyleSheet(stytleStr);
lb_exit->setFont(ft);
lb_exit->setPalette(pa);
lb_exit->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_exit->move((MyApp::DeskWidth * 26) / 30, 0);
//样式
lb_style = new QLabel(wg_up);
lb_style->setText(tr("样式"));
lb_style->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
lb_style->setStyleSheet(stytleStr);
lb_style->setFont(ft);
lb_style->setPalette(pa);
lb_style->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
lb_style->move((MyApp::DeskWidth * 27) / 30, 0);
//最小化
pb_min = new QPushButton(wg_up);
pb_min->setText(tr("-"));
pb_min->setStyleSheet(stytleStr);
pb_min->setFont(ft);
pb_min->setPalette(pa);
pb_min->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
pb_min->move((MyApp::DeskWidth * 28) / 30, 0);
//关闭
pb_close = new QPushButton(wg_up);
pb_close->setText(tr("X"));
pb_close->setStyleSheet(stytleStr);
pb_close->setFont(ft);
pb_close->setPalette(pa);
pb_close->resize(MyApp::DeskWidth / 34, MyApp::DeskHeight / 37);
pb_close->move((MyApp::DeskWidth * 29) / 30, 0);
//构建QTreeWidget,初始化
wg_tree = new QWidget(ui->wg_whole);
wg_tree->resize((MyApp::DeskWidth * 2) / 15, (MyApp::DeskHeight * 35) / 36);
wg_tree->move(0, MyApp::DeskHeight / 36);
vl_tree = new QVBoxLayout(wg_tree);
tw_treeMain = new QTreeWidget(this);
vl_tree->addWidget(tw_treeMain);
//构建主要部分:1个widget、16个label,初始化
wg_main = new QWidget(ui->wg_whole); //部件载体
wg_main->resize((MyApp::DeskWidth * 13) / 15, (MyApp::DeskHeight * 35) / 36);
wg_main->move((MyApp::DeskWidth * 2) / 15, MyApp::DeskHeight / 36);
//wg_main->setSizePolicy(QSizePolicy::Ignored);
QSizePolicy sp_main = wg_main->sizePolicy();
sp_main.setHorizontalPolicy(QSizePolicy::Ignored);
sp_main.setVerticalPolicy(QSizePolicy::Ignored);
wg_main->setSizePolicy(sp_main);
lb_video1 = new QLabel(this);
lb_video2 = new QLabel(this);
lb_video3 = new QLabel(this);
lb_video4 = new QLabel(this);
lb_video5 = new QLabel(this);
lb_video6 = new QLabel(this);
lb_video7 = new QLabel(this);
lb_video8 = new QLabel(this);
lb_video9 = new QLabel(this);
lb_video10 = new QLabel(this);
lb_video11 = new QLabel(this);
lb_video12 = new QLabel(this);
lb_video13 = new QLabel(this);
lb_video14 = new QLabel(this);
lb_video15 = new QLabel(this);
lb_video16 = new QLabel(this);
//构建裂变器,初始化
vl_video = new QVBoxLayout(this);
hl_video1 = new QHBoxLayout(this);
hl_video2 = new QHBoxLayout(this);
hl_video3 = new QHBoxLayout(this);
hl_video4 = new QHBoxLayout(this);
//video初始化并显示
this->InitVideo();
for (int i = 0; i < 4; i++) {
videoLay[0]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = 4; i < 8; i++) {
videoLay[1]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = 8; i < 12; i++) {
videoLay[2]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = 12; i < 16; i++) {
videoLay[3]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
vl_video->addLayout(hl_video1);
vl_video->addLayout(hl_video2);
vl_video->addLayout(hl_video3);
vl_video->addLayout(hl_video4);
vl_video->setSpacing(0);
hl_video1->setSpacing(0);
hl_video2->setSpacing(0);
hl_video3->setSpacing(0);
hl_video4->setSpacing(0);
wg_main->setLayout(vl_video);
}
void FrmMain::InitStyle()
{
this->setStyleSheet("QGroupBox#gboxMain{border-width:0px;}");
this->setProperty("Form", true);
//设置窗体标题栏隐藏--Qt::WindowStaysOnTopHint |
this->setWindowFlags(Qt::FramelessWindowHint |
Qt::WindowSystemMenuHint |
Qt::WindowMinMaxButtonsHint);
}
void FrmMain::InitForm()
{
pb_min->installEventFilter(this);
pb_close->installEventFilter(this);
lb_exit->installEventFilter(this);
lb_full->installEventFilter(this);
lb_style->installEventFilter(this);
menuStyle = new QMenu(this);
menuStyle->addAction("黑色", this, SLOT(changeStyle()));
menuStyle->addAction("白色", this, SLOT(changeStyle()));
menuStyle->addAction("灰色", this, SLOT(changeStyle()));
menuStyle->addAction("蓝色", this, SLOT(changeStyle()));
menuStyle->addAction("银色", this, SLOT(changeStyle()));
menuStyle->setStyleSheet("font: 10pt \"微软雅黑\";");
}
void FrmMain::InitVideo()
{
videoMax = false;
videoLab.append(lb_video1);
videoLab.append(lb_video2);
videoLab.append(lb_video3);
videoLab.append(lb_video4);
videoLab.append(lb_video5);
videoLab.append(lb_video6);
videoLab.append(lb_video7);
videoLab.append(lb_video8);
videoLab.append(lb_video9);
videoLab.append(lb_video10);
videoLab.append(lb_video11);
videoLab.append(lb_video12);
videoLab.append(lb_video13);
videoLab.append(lb_video14);
videoLab.append(lb_video15);
videoLab.append(lb_video16);
videoLay.append(hl_video1);
videoLay.append(hl_video2);
videoLay.append(hl_video3);
videoLay.append(hl_video4);
//设置字号
QFont ft;
ft.setPointSize(16);
//设置颜色
QPalette pa;
pa.setColor(QPalette::WindowText,Qt::black);
//设置StyleSheet
QString stytleStr = "border: 1px solid black;";
for (int i = 0; i < 16; i++) {
videoLab[i]->installEventFilter(this);
videoLab[i]->setProperty("lb_video", true);
videoLab[i]->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
videoLab[i]->setText(QString("通道%1").arg(i + 1));
videoLab[i]->setStyleSheet(stytleStr);
videoLab[i]->setFont(ft);
videoLab[i]->setPalette(pa);
QSizePolicy sp_video = videoLab[i]->sizePolicy();
sp_video.setHorizontalPolicy(QSizePolicy::Ignored);
sp_video.setVerticalPolicy(QSizePolicy::Ignored);
videoLab[i]->setSizePolicy(sp_video);
}
menu = new QMenu(this);
menu->setStyleSheet("font: 10pt \"微软雅黑\";");
menu->addAction("删除当前视频", this, SLOT(DeleteVideoOne()));
menu->addAction("删除所有视频", this, SLOT(DeleteVideoAll()));
menu->addSeparator();
menu->addAction("截图当前视频", this, SLOT(SnapshotVideoOne()));
menu->addAction("截图所有视频", this, SLOT(SnapshotVideoAll()));
menu->addSeparator();
QMenu *menu1 = menu->addMenu("切换到1画面");
menu1->addAction("通道1", this, SLOT(ShowVideo1()));
menu1->addAction("通道2", this, SLOT(ShowVideo1()));
menu1->addAction("通道3", this, SLOT(ShowVideo1()));
menu1->addAction("通道4", this, SLOT(ShowVideo1()));
menu1->addAction("通道5", this, SLOT(ShowVideo1()));
menu1->addAction("通道6", this, SLOT(ShowVideo1()));
menu1->addAction("通道7", this, SLOT(ShowVideo1()));
menu1->addAction("通道8", this, SLOT(ShowVideo1()));
menu1->addAction("通道9", this, SLOT(ShowVideo1()));
menu1->addAction("通道10", this, SLOT(ShowVideo1()));
menu1->addAction("通道11", this, SLOT(ShowVideo1()));
menu1->addAction("通道12", this, SLOT(ShowVideo1()));
menu1->addAction("通道13", this, SLOT(ShowVideo1()));
menu1->addAction("通道14", this, SLOT(ShowVideo1()));
menu1->addAction("通道15", this, SLOT(ShowVideo1()));
menu1->addAction("通道16", this, SLOT(ShowVideo1()));
QMenu *menu4 = menu->addMenu("切换到4画面");
menu4->addAction("通道1-4", this, SLOT(ShowVideo4()));
menu4->addAction("通道5-8", this, SLOT(ShowVideo4()));
menu4->addAction("通道9-12", this, SLOT(ShowVideo4()));
menu4->addAction("通道13-16", this, SLOT(ShowVideo4()));
QMenu *menu9 = menu->addMenu("切换到9画面");
menu9->addAction("通道1-9", this, SLOT(ShowVideo9()));
menu9->addAction("通道8-16", this, SLOT(ShowVideo9()));
menu->addAction("切换到16画面", this, SLOT(ShowVideo16()));
}
void FrmMain::LoadVideo()
{
;
}
void FrmMain::LoadNVRIPC()
{
;
}
bool FrmMain::eventFilter(QObject *obj, QEvent *event)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); //强制类型转换,判断是否是右击
//鼠标按压按键
if (event->type() == QEvent::MouseButtonPress) {
if (obj == pb_min) {
this->showMinimized();
return true;
} else if (obj == pb_close) {
exit(0);
return true;
} else if (obj == lb_exit) {
exit(0);
return true;
} else if (obj == lb_full) {
ScreenFull();
return true;
} else if (obj == lb_style) {
menuStyle->exec(QPoint((MyApp::DeskWidth * 37) / 40, MyApp::DeskHeight / 30));
return true;
} else if (mouseEvent->button() == Qt::RightButton) {
menu->exec(QCursor::pos());
return true;
}
}
//单通道放大和返回
//判断是左、双击
if ((event->type() == QEvent::MouseButtonDblClick) && (mouseEvent->button() == Qt::LeftButton)) {
//判断对应的是label
if (QLabel *lbTmp = qobject_cast<QLabel *>(obj)) {
if (!videoMax) {
RemoveLayout();
videoMax = true;
videoLay[0]->addWidget(lbTmp);
lbTmp->setVisible(true);
} else {
videoMax = false;
ChangeVideoLayout();
}
}
return true;
}
}
void FrmMain::keyPressEvent(QKeyEvent *event)
{
//空格键进入全屏,esc键退出全屏
switch(event->key()) {
case Qt::Key_F1:
ScreenFull();
break;
case Qt::Key_Escape:
ScreenNormal();
break;
default:
QDialog::keyPressEvent(event);
break;
}
}
void FrmMain::ChangeStyle()
{
;
}
void FrmMain::ScreenFull()
{
this->setGeometry(qApp->desktop()->availableGeometry());
this->layout()->setContentsMargins(0, 0, 0, 0);
wg_main->resize(MyApp::DeskWidth, MyApp::DeskHeight);
wg_main->move(0, 0);
wg_up->hide();
wg_tree->hide();
}
void FrmMain::ScreenNormal()
{
this->setGeometry(qApp->desktop()->availableGeometry());
this->layout()->setContentsMargins(1, 1, 1, 1);
wg_main->resize((MyApp::DeskWidth * 13) / 15, (MyApp::DeskHeight * 35) / 36);
wg_main->move((MyApp::DeskWidth * 2) / 15, MyApp::DeskHeight / 36);
//wg_main->layout()->setConte ntsMargins(5, 5, 5, 5);
wg_up->show();
wg_tree->show();
}
void FrmMain::DeleteVideoOne()
{
;
}
void FrmMain::DeleteVideoAll()
{
;
}
void FrmMain::SnapshotVideoOne()
{
;
}
void FrmMain::SnapshotVideoAll()
{
;
}
void FrmMain::ShowVideo1()
{
RemoveLayout();
MyApp::videoType = "1";
videoMax = true;
int index = 0;
QAction *action = (QAction *)sender();
QString name = action->text();
if (name == "通道1") {
index = 0;
} else if (name == "通道2") {
index = 1;
} else if (name == "通道3") {
index = 2;
} else if (name == "通道4") {
index = 3;
} else if (name == "通道5") {
index = 4;
} else if (name == "通道6") {
index = 5;
} else if (name == "通道7") {
index = 6;
} else if (name == "通道8") {
index = 7;
} else if (name == "通道9") {
index = 8;
} else if (name == "通道10") {
index = 9;
} else if (name == "通道11") {
index = 10;
} else if (name == "通道12") {
index = 11;
} else if (name == "通道13") {
index = 12;
} else if (name == "通道14") {
index = 13;
} else if (name == "通道15") {
index = 14;
} else if (name == "通道16") {
index = 15;
}
ChangeVideo1(index);
}
void FrmMain::ChangeVideo1(int index)
{
for (int i = (index + 0); i < (index + 1); i++) {
videoLay[0]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
}
void FrmMain::ShowVideo4()
{
RemoveLayout();
videoMax = false;
int index = 0;
QAction *action = (QAction *)sender();
QString name = action->text();
if (name == "通道1-4") {
index = 0;
MyApp::videoType = "1-4";
} else if (name == "通道5-8") {
index = 4;
MyApp::videoType = "5-8";
} else if (name == "通道9-12") {
index = 8;
MyApp::videoType = "9-12";
} else if (name == "通道13-16") {
index = 12;
MyApp::videoType = "13-16";
}
ChangeVideo4(index);
}
void FrmMain::ChangeVideo4(int index)
{
for (int i = (index + 0); i < (index + 2); i++) {
videoLay[0]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = (index + 2); i < (index + 4); i++) {
videoLay[1]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
}
void FrmMain::ShowVideo9()
{
RemoveLayout();
videoMax = false;
int index = 0;
QAction *action = (QAction *)sender();
QString name = action->text();
if (name == "通道1-9") {
index = 0;
MyApp::videoType = "1-9";
} else if (name == "通道8-16") {
index = 7;
MyApp::videoType = "8-16";
}
ChangeVideo9(index);
}
void FrmMain::ChangeVideo9(int index)
{
for (int i = (index + 0); i < (index + 3); i++) {
videoLay[0]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = (index + 3); i < (index + 6); i++) {
videoLay[1]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = (index + 6); i < (index + 9); i++) {
videoLay[2]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
}
void FrmMain::ShowVideo16()
{
RemoveLayout();
MyApp::videoType = "16";
videoMax = false;
int index = 0;
ChangeVideo16(index);
}
void FrmMain::ChangeVideo16(int index)
{
for (int i = (index + 0); i < (index + 4); i++) {
videoLay[0]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = (index + 4); i < (index + 8); i++) {
videoLay[1]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = (index + 8); i < (index + 12); i++) {
videoLay[2]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
for (int i = (index + 12); i < (index + 16); i++) {
videoLay[3]->addWidget(videoLab[i]);
videoLab[i]->setVisible(true);
}
}
void FrmMain::RemoveLayout()
{
for (int i = 0; i < 4; i++) {
videoLay[0]->removeWidget(videoLab[i]);
videoLab[i]->setVisible(false);
}
for (int i = 4; i < 8; i++) {
videoLay[1]->removeWidget(videoLab[i]);
videoLab[i]->setVisible(false);
}
for (int i = 8; i < 12; i++) {
videoLay[2]->removeWidget(videoLab[i]);
videoLab[i]->setVisible(false);
}
for (int i = 12; i < 16; i++) {
videoLay[3]->removeWidget(videoLab[i]);
videoLab[i]->setVisible(false);
}
}
void FrmMain::ChangeVideoLayout()
{
if (MyApp::videoType == "1-4") {
RemoveLayout();
ChangeVideo4(0);
} else if (MyApp::videoType == "5-8") {
RemoveLayout();
ChangeVideo4(4);
} else if (MyApp::videoType == "9-12") {
RemoveLayout();
ChangeVideo4(8);
} else if (MyApp::videoType == "13-16") {
RemoveLayout();
ChangeVideo4(12);
} else if (MyApp::videoType == "1-9") {
RemoveLayout();
ChangeVideo9(0);
} else if (MyApp::videoType == "8-16") {
RemoveLayout();
ChangeVideo9(7);
} else if (MyApp::videoType == "16") {
RemoveLayout();
ChangeVideo16(0);
}
}
4 发布
4.1 依赖库
细节可见Qt工程的发布
- Qt 的库
方法一:运行执行文件会警告框提示缺失的库文件
方法二:使用windeployqt工具(注会包含未使用的文件)
- 第三方库
方法一:运行执行文件会警告框提示缺失的库文件
方法二:depends工具
4.2 应用程序图标
- 帮助里直接搜“Setting the Application Icon”,详见Qt之设置应用程序图标
5 Qt 知识补充
5.1 编译过程
- qmake生成.pro文件,基于.pro文件,生成Makefile文件
- mingw32-make通过读入Makefile文件完成编译
5.2 .ui文件
- .ui文件是一个XML文件
5.3 Q_OBJECT 与 meta-object system
- The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt’s meta-object system.
- This macro requires the class to be a subclass of QObject.
#include <QObject>
class Counter : public QObject
{
Q_OBJECT
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
private:
int m_value;
};
5.4 Qt为C++带来的功能
- 一种非常强大的无缝对象通信机制,称为信号和插槽
- 可查询和可设计的对象属性
- 强大的事件和事件过滤器
- 用于国际化的上下文字符串翻译
- 复杂的间隔驱动计时器,可以在事件驱动的GUI中优雅地集成许多任务
- 分层和可查询的对象树,以自然的方式组织对象所有权
- 保护指针(QPointer),当被引用的对象被销毁时自动设置为0,这与正常的C ++指针不同,后者在对象被销毁时成为悬空指针
- 跨库边界的动态转换。
- 支持自定义类型创建。
其中许多Qt功能都是使用标准C ++技术实现的,基于QObject的继承。其他如对象通信机制和动态属性系统,需要由Qt自己的元对象编译器(moc)提供的元对象系统。
元对象系统是C ++扩展,使该语言更适合真正的组件GUI编程。
5.5 QWidget类关系图
参考
1、每天一题(48) - C++实现Singleton模式
2、Qt qApp
3、Qt学习之路之鼠标事件
4、Qt 中的事件处理
5、Qt ------ 覆盖eventFilter(),捕获组件事件,事件处理
6、qt事件传递过程和处理–朝问道
7、Qt: qobject_cast(sender()) 简化信号与槽的编写
8、Qt——元对象和属性机制、qobject_cast
9、QT 设置SizePolicy的例子(简单明了)
10、OpenCV3.2+Qt5.8.0+Win10开发视频监控系统----Qt之视频显示窗口固定
11、c – 在Qt中显示解码视频帧的最有效的方法是什么?
12、原来Qt从视频中获取每一帧数据如此简单
13、各种音视频编解码学习详解