为什么要写播放器
学Qt有一段时间了,一直停留在画界面、写按钮的阶段。想找个实际项目练练手,就决定写个视频播放器。看起来简单对吧?不就是放个视频嘛。实际上坑多得超乎想象。
先说结论:最后用Qt的QMediaPlayer + QVideoWidget勉强跑起来了,能播mp4,有播放/暂停/进度条。功能虽然简陋,但踩的坑值得记录一下。
第一个坑:QMediaPlayer的格式支持
文档上说QMediaPlayer支持mp4、avi等常见格式。结果我一跑,黑屏。查了半天才发现,Qt6默认不带媒体后端,需要手动安装qt6-multimedia和对应的gstreamer插件。
# Ubuntu/Debian
sudo apt install qt6-multimedia-dev
sudo apt install gstreamer1.0-plugins-base gstreamer1.0-plugins-good
sudo apt install gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly
装完之后终于能看到画面了。但是!进度条不能拖动。又查了半天,发现是gstreamer版本的问题。总之版本兼容性是个大坑。
第二个坑:信号槽连接
Qt的信号槽机制是核心特性,但新手很容易搞混。比如播放状态改变的信号:
// Qt5写法
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)),
this, SLOT(onStateChanged(QMediaPlayer::State)));
// Qt6写法(推荐)
connect(player, &QMediaPlayer::stateChanged,
this, &MainWindow::onStateChanged);
我一开始抄的Qt5的教程,用SIGNAL/SLOT宏,结果Qt6里很多信号签名变了,编译一堆错误。后来全改成函数指针写法才解决。
Qt6里推荐用函数指针连接信号槽,编译期就能检查类型错误,比字符串宏安全得多。
第三个坑:界面布局
想让视频区域自动填满窗口、进度条在底部固定高度、控制按钮居中。听起来简单,用QVBoxLayout和QHBoxLayout嵌套就行。但是当窗口缩放的时候,视频比例会变形。
解决方法是继承QWidget重写resizeEvent,手动计算16:9的区域。或者更简单的办法:
videoWidget->setAspectRatioMode(Qt::KeepAspectRatio);
一行代码搞定。但这一行代码我找了两个小时。
总结
最终成品功能很简单:打开文件、播放/暂停、进度条、音量控制。代码大概300多行,写了一整天(大部分时间在debug)。
主要收获:
- Qt6的多媒体模块需要额外安装后端
- 信号槽用函数指针写法更靠谱
- QVideoWidget的宽高比设置很重要
- 写GUI程序一定要做好异常处理,不然一个空指针就闪退
学习资源推荐
写这个播放器的过程中,参考了不少资源:
- Qt官方文档:最权威的参考资料,虽然有些地方写得不太清楚,但API列表很全。地址:
doc.qt.io - 零声教育的Qt教程:在Linux.do和Telegram上有人分享过,讲得比较系统,从基础到项目实战都有。适合想系统学习的同学
- Qt官方示例:Qt Creator里自带的Example项目,比文档直观多了。推荐看
mediaplayer相关的示例
零声教育的教程在Linux.do论坛和Telegram频道都能找到免费分享的版本,搜一下就有。
代码放GitHub了:github.com/qwpweee,有兴趣的可以看看。写得不怎么样,但是能跑。