QT入门篇:视频播放器

最近迫于工程需求,开始学习QT编程。

在这个过程中学到的两个点:

  1. 程序不是简单的堆砌,一定要明白自己写的每句话起到的作用是什么;
  2. 细心且耐心,找bug是一个很消磨耐心的事,所以想好了再动手。

本文按步骤介绍自己用QT实现一个简单的视频播放器的过程,介绍在这个过程中遇到的一些入门级知识点,以及解决方式。


入门

1. QT的“跨平台”特点

之前一直只了解QT是跨平台的,但是对“平台”的理解并不准确。

当我们讨论开发应用程序时,平台可能有很多不同的含义,包括操作系统类型、操作系统版本、编译器类型、编译器版本以及处理器架构(32位、64位、ARM等)。

QT框架:广泛应用于创建丰富视觉效果的开源的应用程序开发框架,可以在不同平台之间构建并编译,而几乎不用更改任何一行代码,但前提是应用程序中不使用任何非QT的或特定平台的库。(e.g. 在Windows下编写的程序,如果使用了windows的库,是不能直接迁移到ARM上使用的。) 

2. QT支持的编译器

MSVC , MinGW, GCC

3. OpenCV简介

OpenCV是一个开源、跨平台的库,用于开发计算机视觉应用程序,关注速度与性能,可以分为主模块与附加模块。

OpenCV主模块:

  • 核心功能(core模块),包含由其他所有OpenCV模块使用的所有基本结构、常量和函数,(e.g. Mat类);
  • 图像处理(imgproc模块),包含图像滤波、图像变换的不同算法,(e.g. median, mean,......);
  • 二维特征框架模块(feature2d),包含用于特征提取和匹配的类和方法;(e.g. SURF, SIFT,......)
  • 视频模块,包含用于运动估计、背景差分以及跟踪等主题的算法。

4. 如何在QT的.pro文件中配置OpenCV?

首先,需要选择任意文件夹(通常选择构建OpenCV的文件夹,以确保所有与OpenCV相关的文件都在同一文件夹下),在该文件夹下创建名为“opencv.pri”的文本文件;

Windows用户

(1)在opencv.pri文件中输入以下内容:

INCLUDEPATH += C:/opencv/build/install/include
Debug:{
LIBS += -LC:/opencv/build/install/x64/vc16/lib/opencv_world330d
}
Release:{
LIBS += -LC:/opencv/build/install/x64/vc16/lib/opencv_world330
}

(2)将OpenCV的DLL文件夹添加至系统Path路径,DLL文件夹位置:C:/opencv/build/install/x64/vc16/bin

Macos/Linux用户 

在opencv.pri文件中添加以下内容,不需要配置路径

INCLUDEPATH += /usr/local/include
LIBS += -L/usr/local/lib \
        -lopencv_world

配置.pro文件 

在.pro文件末尾添加:

include(C:/opencv/opencv.pri)

一、界面布局

一上手处于毫无头绪的状态,建立了好几个工程,决定还是先把界面搭出来再动手写代码。这个过程真的是突破了自己“急于求成”的心态和习惯,感觉自己学习编程真的就像野生菌,学得零零散散还不入门,所以这学期总是陷入”我怎么这么菜“的自我怀疑中(一定还是自己写得太少了让这种暴击来得更猛烈些吧)

最终搭建的界面如图1

  • 使用QLabel控件显示图像
  • 包含选择文件,开始、暂停播放,前进、后退,显示当前进度与视频总长度功能;
  • 保存功能:保存单帧,保存一段视频;
  • 显示调节:亮度、对比度调节;放大显示以及显示原图大小。

QT入门篇:视频播放器_第1张图片

                                                                    图1 视频播放器布局及要实现的功能

二、打开文件

这里选择的模式为:点击“打开文件”,弹出“文件选择对话框”,用到的函数为:

https://blog.csdn.net/liyj127/article/details/54090705

QString filename = QFileDialog::getOpenFileName(this, "Open Input File",             
                    QDir::currentPath(), "FileType (*.jpg *png *.bmp)");
if (QFile::exists(filename))
{
    ……
}                

QString转char*

QString  str;
char*  ch;
QByteArray ba = str.toLatin1(); // must
ch=ba.data();

三、QLabel显示图像

这一步麻烦的点在于笔者是从文件中逐字节读取像素值,且需要将数值做灰度映射并显示为8bit灰度图。

  1. 用于存储16-bit与8-bit的像素值的数据类型分别选为了unsigned short与 unsigned char;
  2. 要使用QLable显示图像需要进行数据类型的转换:unsigned char---> QImage---> QPixmap;

unsigned char 数组转QImage

QImage qimg = QImage(&ch[0], img_width, img_height, m_width, QImage::Format_Grayscale8);

第一个参数为char数组地址;第二、三个参数分别为图像的宽和高;第四个参数为图像每行所占的字节数;第五个参数参考QImage格式介绍。

QLable显示图像

// 显示图像大小与QLabel大小相同
ui->ImageLabel->setPixmap(QPixmap::fromImage(qimg).scaled(ui->ImageLabel->size()));

// 显示原图大小
ui->ImageLabel->setPixmap(QPixmap::fromImage(qimg));

// QImage 转 QPixmap
QPixmap pixmap = QPixmap::fromImage(qimg);

四、刷新界面

界面刷新使用QTimer类

// 创建QTimer对象
QTimer* qtimer = new QTimer(this);
 
// 设置刷新频率
qtimer->start(200);  // 每200ms刷新一次

// 或者
qTimer->setInterval(200);
qTimer->start();

// 判断timer的状态
qtimer->isActive();  // true -- 开始刷新;false -- 停止刷新

// 停止刷新
qtimer->stop(); 

// 绑定update()函数
connect(qtimer, SIGNAL(timerout()), this, SLOT(update()));

update()函数可以换成自定义的槽函数,但是该函数中要包含update()函数。 

五、一些Bug

1. 右键控件自动创建槽函数,槽函数被删除后,moc_.....文件编译时报错

解决方式:不仅要在.cpp文件中删除槽函数的定义,还要删除.h文件中槽函数的声明并重新构建项目,不然构建项目时会报错。

2. 自定义槽函数

自定义的槽函数声明时一定要写在 private slots: 下面,比如自定义的与timer绑定的槽函数

不然connect是不会生效的!

3. 慎用指针

 

你可能感兴趣的:(QT编程,编程语言)