Qt5官方demo解析集35——Music Player

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873

接上文Qt5官方demo解析集34——Concentric Circles Example

光看标题大家可能觉得我们今天会聊一聊 Qt 中 multimedia 模块的相关内容,确实,该 demo 基于这个模块实现了一个音乐播放器,不过呢,我们今天更侧重于该 demo 中 winextras 模块的使用。

从名字可以猜到,该模块可以用来为我们提供一些Windows平台上额外的扩展功能,例如DWM(Desktop Window Manager) 特效,Aero Peek,Taskbar,Jump Lists,Thumbnail Toolbar等等,Qt为我们封装了相关 API 使得它们变得更加简单易用。如果大家对这些名词感到陌生,可以前往Qt 官网查看更详细的介绍:http://doc.qt.io/qt-5/qtwinextras-overview.html 。或者,我给大家举几个身边的栗子:

不知道大家有没有留意过,当我们在使用 Qt Creator 进行构建时,其任务栏图标上的进度状态?

或者当我们将鼠标左键放在QQ音乐任务栏图标上时,出现的上一曲、暂停、下一曲这些预览窗口按钮:

亦或是,右键点击QQ音乐出现的最近收听列表:

等等之类,我就不一一列举了,站在GUI的角度来说,这些东西绝不是可有可无的

细节决定成败,用户总是能够在一些小的细节上收获惊喜和感动。

那么,看看我们如何在 Qt 中使用这些贴心的小玩意儿。

记得在pro文件中添加

QT += winextras

然后看看main.cpp,这里面有个实用的关联文件格式的helper函数:

#include "musicplayer.h"

#include <QApplication>
#include <QFileInfo>
#include <QSettings>
#include <QIcon>
#include <QDir>

//! [0]
static void associateFileTypes(const QStringList &fileTypes) // 这是一个helper函数,用来将某文件格式与本程序关联
{
    QString displayName = QGuiApplication::applicationDisplayName();
    QString filePath = QCoreApplication::applicationFilePath();
    QString fileName = QFileInfo(filePath).fileName();

    QSettings settings("HKEY_CURRENT_USER\\Software\\Classes\\Applications\\" + fileName, QSettings::NativeFormat);
    settings.setValue("FriendlyAppName", displayName);

    settings.beginGroup("SupportedTypes");
    foreach (const QString& fileType, fileTypes)
        settings.setValue(fileType, QString());
    settings.endGroup();

    settings.beginGroup("shell");
    settings.beginGroup("open");
    settings.setValue("FriendlyAppName", displayName);
    settings.beginGroup("Command");
    settings.setValue(".", QChar(‘"‘) + QDir::toNativeSeparators(filePath) + QString("\" \"%1\""));
}
//! [0]

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    app.setApplicationName("MusicPlayer");
    app.setOrganizationName("QtWinExtras");
    app.setOrganizationDomain("qt-project.org");
    app.setApplicationDisplayName("QtWinExtras Music Player");
    app.setWindowIcon(QIcon(":/logo.png"));

    associateFileTypes(QStringList(".mp3"));                // helper函数的使用方式

    MusicPlayer player;
    const QStringList arguments = QCoreApplication::arguments();
    if (arguments.size() > 1)                              // 如果打开参数包含文件名
        player.playFile(arguments.at(1));                  // 则开始播放第一首
    player.resize(300, 60);
    player.show();

    return app.exec();
}

VolumeButton 类继承自QToolButton,使用 Qt 中的标准音量图像设置为自身图标,

setIcon(style()->standardIcon(QStyle::SP_MediaVolume));

并提供了一个可以调节音量的弹出菜单,并根据DWM的混合状态决定自身的显示状态,代码都很容易理解,就不贴出来了。

在MusicPlayer类中,首先记得

#include <QtWinExtras>

然后我们通过下面的函数来创建Jump Lists:

void MusicPlayer::createJumpList()
{
    QWinJumpList jumplist;
    jumplist.recent()->setVisible(true);
}

Taskbar的创建与Progress类似,我们将其与窗口上的进度条关联起来:

void MusicPlayer::createTaskbar()
{
    taskbarButton = new QWinTaskbarButton(this);
    taskbarButton->setWindow(windowHandle());  // 使用窗口句柄作为参数

    taskbarProgress = taskbarButton->progress();
    connect(positionSlider, SIGNAL(valueChanged(int)), taskbarProgress, SLOT(setValue(int)));
    connect(positionSlider, SIGNAL(rangeChanged(int,int)), taskbarProgress, SLOT(setRange(int,int)));

    connect(&mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(updateTaskbar()));
}

要创建预览窗口按钮,首先需要创建一个QWinThumbnailToolBar,然后在上面添加按钮:

void MusicPlayer::createThumbnailToolBar()
{
    thumbnailToolBar = new QWinThumbnailToolBar(this);
    thumbnailToolBar->setWindow(windowHandle());

    playToolButton = new QWinThumbnailToolButton(thumbnailToolBar);
    playToolButton->setEnabled(false);
    playToolButton->setToolTip(tr("Play"));
    playToolButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
    connect(playToolButton, SIGNAL(clicked()), this, SLOT(togglePlayback()));

    forwardToolButton = new QWinThumbnailToolButton(thumbnailToolBar);
    forwardToolButton->setEnabled(false);
    forwardToolButton->setToolTip(tr("Fast forward"));
    forwardToolButton->setIcon(style()->standardIcon(QStyle::SP_MediaSeekForward));
    connect(forwardToolButton, SIGNAL(clicked()), this, SLOT(seekForward()));

    backwardToolButton = new QWinThumbnailToolButton(thumbnailToolBar);
    backwardToolButton->setEnabled(false);
    backwardToolButton->setToolTip(tr("Rewind"));
    backwardToolButton->setIcon(style()->standardIcon(QStyle::SP_MediaSeekBackward));
    connect(backwardToolButton, SIGNAL(clicked()), this, SLOT(seekBackward()));

    thumbnailToolBar->addButton(backwardToolButton);
    thumbnailToolBar->addButton(playToolButton);
    thumbnailToolBar->addButton(forwardToolButton);

    connect(&mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(updateThumbnailToolBar()));
    connect(&mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(updateThumbnailToolBar()));
    connect(&mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(updateThumbnailToolBar()));
}

最后我们看看程序运行效果:

在Win7下当我们暂停播放时,任务栏会出现一个暂停样式的图标,而在Win8中则表现为绿色的进度条变成了黄色:

时间: 2024-11-08 01:07:15

Qt5官方demo解析集35——Music Player的相关文章

Qt5官方demo解析集35——Music Player(使用winextras模块)

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集34——Concentric Circles Example 光看标题大家可能觉得我们今天会聊一聊 Qt 中 multimedia 模块的相关内容,确实,该 demo 基于这个模块实现了一个音乐播放器,不过呢,我们今天更侧重于该 demo 中 winextras 模块的使用. 从名字可以猜到,该模块可以用来为我们提供一些W

Qt5官方demo解析集36——Wiggly Example

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集35--Music Player 今天同样带来一个有趣的小例子,如下图所示,我们输入的文字将在中央窗口显示并以正弦波形浮动. 这个例子中涉及到 Qt 定时器族中的 QBasicTimer 类以及十分实用的 QFontMetrics 类. 当我们将应用部署在移动设备上时,Qt 将为该应用添加 "-small-screen&q

Qt5官方demo解析集31——StocQt

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集30--Extending QML - Binding Example 最近在做QML制表,因此想找一些相关曲线绘制的demo看看,结果发现了这个例子,觉得挺不错,它相比于我们之前的Extend和Particle系列显得更大一些,涉及到的面也更广一些.因此想拿过来给大家分享~ 这个例子是基于QML的股票走势图绘制,数据来源

Qt5官方demo解析集11——Qt Quick Particles Examples - Affectors

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集10--Qt Quick Particles Examples - Emitters Affectors是Qt官方粒子系统demo中的第二个例程,它是在Emitters上的进一步扩展.我们将看到,通过使用Affectors,我们能够创造更加灵活的粒子显示以及交互行为. 首先还是看下介绍:This is a collecti

Qt5官方demo解析集33——Qt Quick Examples - Window and Screen

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集32--Qt Quick Examples - Threading 来到我们Qt Quick Examples的第二个例子了,之所以挑这个demo,主要是我们使用Qt开发界面(尤其是跨平台界面)时,本地屏幕信息与窗口调用是不可避免的课题. 这个例子便向我们展示了在QML中获取本地屏幕信息的方法. 项目树如图,其中share

Qt5官方demo解析集15——Chapter 1: Creating a New Type

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 前面我们说到了QML的粒子系统,它可以创造丰富多彩的粒子特效.但是更多的情况下,我们的QML界面是配合C++进行工作的:QML负责界面渲染,C++负责逻辑事务.甚至有时,我们还会利用QML来绘制C++代码中定义的可视化组件,或者使用C++代码来访问QML中对象的属性等.从这篇博文开始,我们介绍了Qt官方Demo中的"Chapter"系列,它介

Qt5官方demo解析集17——Chapter 3: Adding Property Bindings

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集16--Chapter 2: Connecting to C++ Methods and Signals 在C++中我们通常将用户的交互与处理函数用信号槽绑定起来,比如窗口尺寸的变化,颜色的变化等,但在QML中,我们更多的使用属性绑定来完成这些功能.我们可以将这个属性值绑定到另一个对象或者本身的属性值上,这样当后者改变时,

Qt5官方demo解析集16——Chapter 2: Connecting to C++ Methods and Signals

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集15--Chapter 1: Creating a New Type 在上篇博文我们了解到如何在C++代码中将一个C++类注册为一个QML类型,并供QML文件使用.接下来这个Demo中进一步向这个PieChart中添加信号和方法供QML使用. 在项目上没有什么改变,我们直接来看代码PieChart.h: #ifndef P

Qt5官方demo解析集18——Chapter 4: Using Custom Property Types

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集17--Chapter 3: Adding Property Bindings 在前面的"饼状图"Demo中,我们为这个自定义类型定义了"name"和"color"属性,他们都是基于Qt内置类型"QString"和"QColor",这