本帖最后由 正点原子运营 于 2022-8-10 17:57 编辑
1)实验平台:正点原子阿尔法Linux开发板
2) 章节摘自【正点原子】《I.MX6U 嵌入式Qt开发指南》
3)购买链接:https://detail.tmall.com/item.htm?id=609033604451
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/arm-linux/zdyz-i.mx6ull.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子阿尔法Linux交流群:1027879335
第十二章 多媒体 第九章12.4 视频播放器与音乐播放器一样使用QMediaPlayer类,不同的是需要使用setVideoOutput(QVideoWidget*)设置一个视频输出窗口,好让视频在此窗口显示,其他步骤基本都一样。
第十章12.4.1 应用实例本例设计一个比较好看且简洁的视频播放器,界面是编者原创界面。 本例目的:视频播放器的设计与使用。 例15_videoplayer,视频播放器(难度:中等)。项目路径为Qt/2/15_videoplayer。注意本例有用到qss样式文件,关于如何添加资源文件与qss文件请参考7.1.3小节。音乐播放器的功能这些都为大家所熟知,不用编者介绍了。 项目文件15_videoplayer.pro文件第一行添加的代码部分如下。 - 15_videoplayer.pro编程后的代码
- 1 QT += core gui multimedia multimediawidgets
- 2
- 3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
- 4
- 5 CONFIG += c++11
- 6
- 7 # The following define makes your compiler emit warnings if you use
- 8 # any Qt feature that has been marked deprecated (the exact warnings
- 9 # depend on your compiler). Please consult the documentation of the
- 10 # deprecated API in order to know how to port your code away from it.
- 11 DEFINES += QT_DEPRECATED_WARNINGS
- 12
- 13 # You can also make your code fail to compile if it uses deprecated APIs.
- 14 # In order to do so, uncomment the following line.
- 15 # You can also select to disable deprecated APIs only up to a certain version of Qt.
- 16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
- 17
- 18 SOURCES += \
- 19 main.cpp \
- 20 mainwindow.cpp
- 21
- 22 HEADERS += \
- 23 mainwindow.h
- 24
- 25 # Default rules for deployment.
- 26 qnx: target.path = /tmp/${TARGET}/bin
- 27 else: unix:!android: target.path = /opt/${TARGET}/bin
- 28 !isEmpty(target.path): INSTALLS += target
- 29
- 30 RESOURCES += \
- 31 res.qrc
复制代码 在头文件“mainwindow.h”具体代码如下
头文件里主要是声明界面所使用的元素及一些槽函数。 在源文件“mainwindow.cpp”具体代码如下。 - mainwindow.cpp编程后的代码
- /******************************************************************
- Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.
- * @projectName 15_videoplayer
- * @brief mainwindow.cpp
- * @author Deng Zhimao
- * @email 1252699831@qq.com
- * @net www.openedv.com
- * @date 2021-04-27
- *******************************************************************/
- 1 #include "mainwindow.h"
- 2 #include <QCoreApplication>
- 3 #include <QFileInfoList>
- 4 #include <QDir>
- 5
- 6 MainWindow::MainWindow(QWidget *parent)
- 7 : QMainWindow(parent)
- 8 {
- 9 /* 视频播放器布局初始化 */
- 10 videoLayout();
- 11
- 12 /* 媒体初始化 */
- 13 mediaPlayerInit();
- 14
- 15 /* 扫描本地视频 */
- 16 scanVideoFiles();
- 17
- 18 /* 设置按钮的属性 */
- 19 pushButton[0]->setCheckable(true);
- 20 pushButton[4]->setCheckable(true);
- 21
- 22 /* 按钮连接信号槽 */
- 23 connect(pushButton[0], SIGNAL(clicked()),
- 24 this, SLOT(btn_play_clicked()));
- 25 connect(pushButton[1], SIGNAL(clicked()),
- 26 this, SLOT(btn_next_clicked()));
- 27 connect(pushButton[2], SIGNAL(clicked()),
- 28 this, SLOT(btn_volmedown_clicked()));
- 29 connect(pushButton[3], SIGNAL(clicked()),
- 30 this, SLOT(btn_volmeup_clicked()));
- 31 connect(pushButton[4], SIGNAL(clicked()),
- 32 this, SLOT(btn_fullscreen_clicked()));
- 33
- 34 /* 列表连接信号槽 */
- 35 connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)),
- 36 this, SLOT(listWidgetCliked(QListWidgetItem*)));
- 37
- 38 /* 媒体连接信号槽 */
- 39 connect(videoPlayer,
- 40 SIGNAL(stateChanged(QMediaPlayer::State)),
- 41 this,
- 42 SLOT(mediaPlayerStateChanged(QMediaPlayer::State)));
- 43 connect(mediaPlaylist,
- 44 SIGNAL(currentIndexChanged(int)),
- 45 this,
- 46 SLOT(mediaPlaylistCurrentIndexChanged(int)));
- 47 connect(videoPlayer, SIGNAL(durationChanged(qint64)),
- 48 this,
- 49 SLOT(musicPlayerDurationChanged(qint64)));
- 50 connect(videoPlayer,
- 51 SIGNAL(positionChanged(qint64)),
- 52 this,
- 53 SLOT(mediaPlayerPositionChanged(qint64)));
- 54
- 55 /* slider信号槽连接 */
- 56 connect(durationSlider, SIGNAL(sliderReleased()),
- 57 this, SLOT(durationSliderReleased()));
- 58 connect(volumeSlider, SIGNAL(sliderReleased()),
- 59 this, SLOT(volumeSliderReleased()));
- 60 }
- 61
- 62 MainWindow::~MainWindow()
- 63 {
- 64 }
- 65
- 66 void MainWindow::videoLayout()
- 67 {
- 68 /* 设置位置与大小,这里固定为800, 480 */
- 69 this->setGeometry(0, 0, 800, 480);
- 70 // this->setMinimumSize(800, 480);
- 71 // this->setMaximumSize(800, 480);
- 72 QPalette pal;
- 73 pal.setColor(QPalette::WindowText, Qt::white);
- 74
- 75 for (int i = 0; i < 3; i++) {
- 76 /* 水平容器 */
- 77 hWidget[i] = new QWidget();
- 78 hWidget[i]->setAutoFillBackground(true);
- 79 /* 水平布局 */
- 80 hBoxLayout[i] = new QHBoxLayout();
- 81 }
- 82
- 83 for (int i = 0; i < 2; i++) {
- 84 /* 垂直容器 */
- 85 vWidget[i] = new QWidget();
- 86 vWidget[i]->setAutoFillBackground(true);
- 87 /* 垂直布局 */
- 88 vBoxLayout[i] = new QVBoxLayout();
- 89 }
- 90
- 91 for (int i = 0; i < 2; i++) {
- 92 label[i] = new QLabel();
- 93 }
- 94
- 95 for (int i = 0; i < 5; i++) {
- 96 pushButton[i] = new QPushButton();
- 97 pushButton[i]->setMaximumSize(44, 44);
- 98 pushButton[i]->setMinimumSize(44, 44);
- 99 }
- 100
- 101 /* 设置 */
- 102 vWidget[0]->setObjectName("vWidget0");
- 103 vWidget[1]->setObjectName("vWidget1");
- 104 hWidget[1]->setObjectName("hWidget1");
- 105 hWidget[2]->setObjectName("hWidget2");
- 106 pushButton[0]->setObjectName("btn_play");
- 107 pushButton[1]->setObjectName("btn_next");
- 108 pushButton[2]->setObjectName("btn_volumedown");
- 109 pushButton[3]->setObjectName("btn_volumeup");
- 110 pushButton[4]->setObjectName("btn_screen");
- 111
- 112 QFont font;
- 113
- 114 font.setPixelSize(18);
- 115 label[0]->setFont(font);
- 116 label[1]->setFont(font);
- 117
- 118 pal.setColor(QPalette::WindowText, Qt::white);
- 119 label[0]->setPalette(pal);
- 120 label[1]->setPalette(pal);
- 121
- 122 label[0]->setText("00:00");
- 123 label[1]->setText("/00:00");
- 124
- 125 durationSlider = new QSlider(Qt::Horizontal);
- 126 durationSlider->setMaximumHeight(15);
- 127 durationSlider->setObjectName("durationSlider");
- 128
- 129 volumeSlider = new QSlider(Qt::Horizontal);
- 130 volumeSlider->setRange(0, 100);
- 131 volumeSlider->setMaximumWidth(80);
- 132 volumeSlider->setObjectName("volumeSlider");
- 133 volumeSlider->setValue(50);
- 134
- 135 listWidget = new QListWidget();
- 136 listWidget->setObjectName("listWidget");
- 137 listWidget->setVerticalScrollBarPolicy(
- 138 Qt::ScrollBarAlwaysOff);
- 139 listWidget->setHorizontalScrollBarPolicy(
- 140 Qt::ScrollBarAlwaysOff);
- 141 //listWidget->setFocusPolicy(Qt::NoFocus);
- 142 videoWidget = new QVideoWidget();
- 143 videoWidget->setStyleSheet("border-image: none;"
- 144 "background: transparent;"
- 145 "border:none");
- 146
- 147 /* H0布局 */
- 148 vWidget[0]->setMinimumSize(300, 480);
- 149 vWidget[0]->setMaximumWidth(300);
- 150 videoWidget->setMinimumSize(500, 480);
- 151
- 152 hBoxLayout[0]->addWidget(videoWidget);
- 153 hBoxLayout[0]->addWidget(vWidget[0]);
- 154
- 155 hWidget[0]->setLayout(hBoxLayout[0]);
- 156 hBoxLayout[0]->setContentsMargins(0, 0, 0, 0);
- 157
- 158 setCentralWidget(hWidget[0]);
- 159
- 160 /* V0布局 */
- 161 QSpacerItem *vSpacer0 = new
- 162 QSpacerItem(0, 80,
- 163 QSizePolicy::Minimum,
- 164 QSizePolicy::Maximum);
- 165 vBoxLayout[0]->addWidget(listWidget);
- 166 vBoxLayout[0]->addSpacerItem(vSpacer0);
- 167 vBoxLayout[0]->setContentsMargins(0, 0, 0, 0);
- 168
- 169 vWidget[0]->setLayout(vBoxLayout[0]);
- 170
- 171 /* V1布局 */
- 172 /* 底板部件布局 */
- 173 hWidget[1]->setMaximumHeight(15);
- 174 hWidget[2]->setMinimumHeight(65);
- 175 vBoxLayout[1]->addWidget(hWidget[1]);
- 176 vBoxLayout[1]->addWidget(hWidget[2]);
- 177 vBoxLayout[1]->setAlignment(Qt::AlignCenter);
- 178
- 179 vWidget[1]->setLayout(vBoxLayout[1]);
- 180 vWidget[1]->setParent(this);
- 181 vWidget[1]->setGeometry(0, this->height() - 80, this->width(), 80);
- 182 vBoxLayout[1]->setContentsMargins(0, 0, 0, 0);
- 183 /* 位于最上层 */
- 184 vWidget[1]->raise();
- 185
- 186 /* H1布局 */
- 187 hBoxLayout[1]->addWidget(durationSlider);
- 188 hBoxLayout[1]->setContentsMargins(0, 0, 0, 0);
- 189 hWidget[1]->setLayout(hBoxLayout[1]);
- 190
- 191 /* H2布局 */
- 192 QSpacerItem *hSpacer0 = new
- 193 QSpacerItem(300, 80,
- 194 QSizePolicy::Expanding,
- 195 QSizePolicy::Maximum);
- 196
- 197 hBoxLayout[2]->addSpacing(20);
- 198 hBoxLayout[2]->addWidget(pushButton[0]);
- 199 hBoxLayout[2]->addSpacing(10);
- 200 hBoxLayout[2]->addWidget(pushButton[1]);
- 201 hBoxLayout[2]->addSpacing(10);
- 202 hBoxLayout[2]->addWidget(pushButton[2]);
- 203 hBoxLayout[2]->addWidget(volumeSlider);
- 204 hBoxLayout[2]->addWidget(pushButton[3]);
- 205 hBoxLayout[2]->addWidget(label[0]);
- 206 hBoxLayout[2]->addWidget(label[1]);
- 207 hBoxLayout[2]->addSpacerItem(hSpacer0);
- 208 hBoxLayout[2]->addWidget(pushButton[4]);
- 209 hBoxLayout[2]->addSpacing(20);
- 210 hBoxLayout[2]->setContentsMargins(0, 0, 0, 0);
- 211 hBoxLayout[2]->setAlignment(Qt::AlignLeft | Qt::AlignTop);
- 212
- 213 hWidget[2]->setLayout(hBoxLayout[2]);
- 214 }
- 215
- 216 void MainWindow::mediaPlayerInit()
- 217 {
- 218 videoPlayer = new QMediaPlayer(this);
- 219 mediaPlaylist = new QMediaPlaylist(this);
- 220 /* 确保列表是空的 */
- 221 mediaPlaylist->clear();
- 222 /* 设置视频播放器的列表为mediaPlaylist */
- 223 videoPlayer->setPlaylist(mediaPlaylist);
- 224 /* 设置视频输出窗口 */
- 225 videoPlayer->setVideoOutput(videoWidget);
- 226 /* 设置播放模式,Loop是列循环 */
- 227 mediaPlaylist->setPlaybackMode(QMediaPlaylist::Loop);
- 228 /* 设置默认软件音量为50% */
- 229 videoPlayer->setVolume(50);
- 230 }
- 231
- 232 void MainWindow::resizeEvent(QResizeEvent *event)
- 233 {
- 234 Q_UNUSED(event);
- 235 vWidget[1]->setGeometry(0, this->height() - 80, this->width(), 80);
- 236 }
- 237
- 238 void MainWindow::btn_play_clicked()
- 239 {
- 240 int state = videoPlayer->state();
- 241 switch (state) {
- 242 case QMediaPlayer::StoppedState:
- 243 /* 媒体播放 */
- 244 videoPlayer->play();
- 245 break;
- 246
- 247 case QMediaPlayer::PlayingState:
- 248 /* 媒体暂停 */
- 249 videoPlayer->pause();
- 250 break;
- 251
- 252 case QMediaPlayer::PausedState:
- 253 /* 设置视频输出窗口 */
- 254 videoPlayer->play();
- 255 break;
- 256 }
- 257 }
- 258
- 259 void MainWindow::btn_next_clicked()
- 260 {
- 261 videoPlayer->stop();
- 262 int count = mediaPlaylist->mediaCount();
- 263 if (0 == count)
- 264 return;
- 265
- 266 /* 列表下一个 */
- 267 mediaPlaylist->next();
- 268 videoPlayer->play();
- 269 }
- 270
- 271 void MainWindow::btn_volmeup_clicked()
- 272 {
- 273 /* 点击每次音量+5 */
- 274 volumeSlider->setValue(volumeSlider->value() + 5);
- 275 videoPlayer->setVolume(volumeSlider->value());
- 276 }
- 277
- 278 void MainWindow::btn_fullscreen_clicked()
- 279 {
- 280 /* 全屏/非全屏操作 */
- 281 vWidget[0]->setVisible(!pushButton[4]->isChecked());
- 282 }
- 283
- 284 void MainWindow::btn_volmedown_clicked()
- 285 {
- 286 /* 点击每次音量-5 */
- 287 volumeSlider->setValue(volumeSlider->value() - 5);
- 288 videoPlayer->setVolume(volumeSlider->value());
- 289 }
- 290
- 291 void MainWindow::mediaPlayerStateChanged(
- 292 QMediaPlayer::State
- 293 state)
- 294 {
- 295 switch (state) {
- 296 case QMediaPlayer::StoppedState:
- 297 pushButton[0]->setChecked(false);
- 298 break;
- 299
- 300 case QMediaPlayer::PlayingState:
- 301 pushButton[0]->setChecked(true);
- 302 break;
- 303
- 304 case QMediaPlayer::PausedState:
- 305 pushButton[0]->setChecked(false);
- 306 break;
- 307 }
- 308 }
- 309
- 310 void MainWindow::listWidgetCliked(QListWidgetItem *item)
- 311 {
- 312 videoPlayer->stop();
- 313 mediaPlaylist->setCurrentIndex(listWidget->row(item));
- 314 videoPlayer->play();
- 315 }
- 316
- 317 void MainWindow::mediaPlaylistCurrentIndexChanged(
- 318 int index)
- 319 {
- 320 if (-1 == index)
- 321 return;
- 322
- 323 /* 设置列表正在播放的项 */
- 324 listWidget->setCurrentRow(index);
- 325 }
- 326
- 327 void MainWindow::musicPlayerDurationChanged(
- 328 qint64 duration)
- 329 {
- 330 durationSlider->setRange(0, duration / 1000);
- 331 int second = duration / 1000;
- 332 int minute = second / 60;
- 333 second %= 60;
- 334
- 335 QString mediaDuration;
- 336 mediaDuration.clear();
- 337
- 338 if (minute >= 10)
- 339 mediaDuration = QString::number(minute, 10);
- 340 else
- 341 mediaDuration = "0" + QString::number(minute, 10);
- 342
- 343 if (second >= 10)
- 344 mediaDuration = mediaDuration
- 345 + ":" + QString::number(second, 10);
- 346 else
- 347 mediaDuration = mediaDuration
- 348 + ":0" + QString::number(second, 10);
- 349
- 350 /* 显示媒体总长度时间 */
- 351 label[1]->setText("/" + mediaDuration);
- 352 }
- 353
- 354 void MainWindow::mediaPlayerPositionChanged(
- 355 qint64 position)
- 356 {
- 357 if (!durationSlider->isSliderDown())
- 358 durationSlider->setValue(position / 1000);
- 359
- 360 int second = position / 1000;
- 361 int minute = second / 60;
- 362 second %= 60;
- 363
- 364 QString mediaPosition;
- 365 mediaPosition.clear();
- 366
- 367 if (minute >= 10)
- 368 mediaPosition = QString::number(minute, 10);
- 369 else
- 370 mediaPosition = "0" + QString::number(minute, 10);
- 371
- 372 if (second >= 10)
- 373 mediaPosition = mediaPosition
- 374 + ":" + QString::number(second, 10);
- 375 else
- 376 mediaPosition = mediaPosition
- 377 + ":0" + QString::number(second, 10);
- 378
- 379 /* 显示现在播放的时间 */
- 380 label[0]->setText(mediaPosition);
- 381 }
- 382
- 383 void MainWindow::durationSliderReleased()
- 384 {
- 385 /* 设置媒体播放的位置 */
- 386 videoPlayer->setPosition(durationSlider->value() * 1000);
- 387 }
- 388
- 389 void MainWindow::volumeSliderReleased()
- 390 {
- 391 /* 设置音量 */
- 392 videoPlayer->setVolume(volumeSlider->value());
- 393 }
- 394
- 395 void MainWindow::scanVideoFiles()
- 396 {
- 397 QDir dir(QCoreApplication::applicationDirPath()
- 398 + "/myVideo");
- 399 QDir dirbsolutePath(dir.absolutePath());
- 400 /* 如果目录存在 */
- 401 if (dirbsolutePath.exists()) {
- 402 /* 定义过滤器 */
- 403 QStringList filter;
- 404 /* 包含所有xx后缀的文件 */
- 405 filter << "*.mp4" << "*.mkv" << "*.wmv" << "*.avi";
- 406 /* 获取该目录下的所有文件 */
- 407 QFileInfoList files =
- 408 dirbsolutePath.entryInfoList(filter, QDir::Files);
- 409 /* 遍历 */
- 410 for (int i = 0; i < files.count(); i++) {
- 411 MediaObjectInfo info;
- 412 /* 使用utf-8编码 */
- 413 info.fileName = QString::fromUtf8(files.at(i)
- 414 .fileName()
- 415 .toUtf8()
- 416 .data());
- 417 info.filePath = QString::fromUtf8(files.at(i)
- 418 .filePath()
- 419 .toUtf8()
- 420 .data());
- 421 /* 媒体列表添加视频 */
- 422 if (mediaPlaylist->addMedia(
- 423 QUrl::fromLocalFile(info.filePath))) {
- 424 /* 添加到容器数组里储存 */
- 425 mediaObjectInfo.append(info);
- 426 /* 添加视频名字至列表 */
- 427 listWidget->addItem(info.fileName);
- 428 } else {
- 429 qDebug()<<
- 430 mediaPlaylist->errorString()
- 431 .toUtf8().data()
- 432 << endl;
- 433 qDebug()<< " Error number:"
- 434 << mediaPlaylist->error()
- 435 << endl;
- 436 }
- 437 }
- 438 }
- 439 }
复制代码 与上一小节音乐播放器的一样,在构造函数里布局初始化,然后执行扫描本地视频文件。之后就是一些信号槽的连接,基本上就是这么一个流程了。 第395~439行,扫本地目录的视频文件,通过过滤文件名的后缀,将视频文件名添加至媒体列表里,就可以点击播放了,需要更多的格式的视频文件,可以自己尝试修改需要过滤的文件名。 main .cpp内容如下,主要是加载qss样式文件。没有什么可讲解。 - 1 #include "mainwindow.h"
- 2
- 3 #include <QApplication>
- 4 #include <QFile>
- 5
- 6 int main(int argc, char *argv[])
- 7 {
- 8 QApplication a(argc, argv);
- 9 /* 指定文件 */
- 10 QFile file(":/style.qss");
- 11
- 12 /* 判断文件是否存在 */
- 13 if (file.exists() ) {
- 14 /* 以只读的方式打开 */
- 15 file.open(QFile::ReadOnly);
- 16 /* 以字符串的方式保存读出的结果 */
- 17 QString styleSheet = QLatin1String(file.readAll());
- 18 /* 设置全局样式 */
- 19 qApp->setStyleSheet(styleSheet);
- 20 /* 关闭文件 */
- 21 file.close();
- 22 }
- 23
- 24 MainWindow w;
- 25 w.show();
- 26 return a.exec();
- 27 }
复制代码style.qss样式文件如下。素材已经在源码处提供。注意下面的style.qss不能有注释! 第十一章12.4.2 程序运行效果先点击构建项目,项目构建完成后,再将本例的myVideo视频文件夹拷贝到可执行程序的文件夹同一级目录下,也就是build-15_videoplayer-Desktop_Qt_5_12_9_GCC_64bit-Debug目录下。再重新运行,就出现视频文件在列表里,如下图,点击播放即可播放视频。 默认列表,未播放前。 开始播放,未全屏状态。 全屏状态。
|