QT5:C++實現基於multimedia的音樂播放器(一)

来源:https://www.cnblogs.com/guolao/archive/2018/04/23/8922552.html
-Advertisement-
Play Games

上一篇里簡略的描述了一下播放器的實現,這一篇開始具體描述一下過程。 環境配置:Qt Creator 打開Qt Creator,創建一個new project,項目名稱隨你喜歡(我的是MusicPlayer),類名也隨你喜歡(我的是Music),基類選擇QWidget,不勾選界面UI(你也可以勾選UI ...


上一篇里簡略的描述了一下播放器的實現,這一篇開始具體描述一下過程。

環境配置:Qt Creator

打開Qt Creator,創建一個new project,項目名稱隨你喜歡(我的是MusicPlayer),類名也隨你喜歡(我的是Music),基類選擇QWidget,不勾選界面UI(你也可以勾選UI,用QT自帶的UI設計來創建界面),然後要記住項目保存路徑不能有中文

創建成功後,在MusicPlayer.pro(項目名稱.pro)裡加上“QT += multimedia”這一句:

1 QT += core gui
2 QT += multimedia
3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

然後在頭文件music.h(類名.h)里添加要用到的頭文件名:

 1 #include <QWidget>
 2 #include <QMediaPlayer>
 3 #include <QPushButton>
 4 #include <QSlider>
 5 #include <QLabel>
 6 #include <QTime>
 7 #include <QPaintEvent>
 8 #include <QMediaPlaylist>
 9 #include <QTimer>
10 #include <QListWidget>

並且在music類里寫上要用到的對象成員和函數:

 1 class Music : public QWidget
 2 {
 3     Q_OBJECT
 4 public:
 5     explicit Music(QWidget *parent = 0);
 6     static int z;
 7 
 8 public slots:
 9     void addMoremusic();
10     void playMusic();
11     void preMusic();
12     void nextMusic();
13     void meteOpen();
14     void volumChange(int);
15     void positionChange(qint64 position);
16     void showMessage(bool);
17     void seekChange(int position);
18     void posChange();
19     void clearMessage();
20     void musicPlayPattern();
21 
22 private:
23     void init_controls();
24     void init_skin();
25 
26     QPushButton *BtnClose;
27     QPushButton *BtnMin;
28     QPushButton *BtnPlay;
29     QPushButton *BtnPrev;
30     QPushButton *BtnNext;
31     QPushButton *muteButton;
32     QPushButton *addMore;
33     QPushButton *playPattern;
34     QSlider     *volumeControl;
35     QSlider     *seekSlider;
36     QLabel      *showTime;
37     QLabel      *showPro;
38     QLabel      *showMge;
39     QLabel      *title;
40     QLabel      *message;
41     QListWidget *list;
42     bool        add;
43     QTimer      *timer;
44     QTimer      *timer2;
45     int         moved;
46     QPoint      dragPosition;
47     QMediaPlayer   *player;
48     QMediaPlaylist * playList;
49 
50 protected:
51     void paintEvent(QPaintEvent *event);
52     void mousePressEvent(QMouseEvent *event);
53     void mouseMoveEvent(QMouseEvent *event);
54 };
View Code

還要在源文件music.cpp裡加上要用的頭文件名:

 1 #include "music.h"
 2 #include <QPixmap>
 3 #include <QFile>
 4 #include <QPainter>
 5 #include <QFileDialog>
 6 #include <QUrl>
 7 #include <QDebug>
 8 #include <QMediaMetaData>
 9 #include <QMessageBox>
10 #include <QFileInfo>

接著添加資源文件,把要用的圖標和背景圖片都添加到項目里,然後就可以在music.cpp里寫播放器的界面了。

 1 Music::Music(QWidget *parent) : QWidget(parent)
 2 {
 3     QPixmap background;
 4     background.load(":/image/music_bg.bmp");//載入背景圖片
 5     this -> resize(background.width(),background.height());//設置視窗和背景圖片大小一致
 6     this -> setWindowFlags(Qt::FramelessWindowHint);//產生一個無視窗邊框的視窗,用戶無法改變它的大小也無法移動它
 7     add = false;
 8     moved = 0;
 9     timer = new QTimer(this);
10     timer2 = new QTimer(this);
11 
12     player = new QMediaPlayer(this);//QMediaplayer用於解析音頻文件和視頻文件
13     playList = new QMediaPlaylist;
14     
15     init_controls();//創建按鈕
16     init_skin();//外部載入qss文件,繪製界面樣式
17 
18     connect(player, SIGNAL(metaDataAvailableChanged(bool)), this, SLOT(showMessage(bool)));
19     connect(seekSlider,SIGNAL(sliderMoved(int)), this,SLOT(seekChange(int)));
20 }

因為我創建的是一個無法移動的窗體,所以重寫滑鼠左鍵函數來讓它可以被移動,這樣的話,滑鼠左鍵按住時可以拖動窗體了:

//令視窗可以被拖動
void Music::mousePressEvent(QMouseEvent *event){
    if(event->buttons()==Qt::LeftButton)
    {
        dragPosition=event->globalPos()-frameGeometry().topLeft();
        event->accept();
    }
}

void Music::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)//event->buttons()==Qt::LeftButton && event ->y() < 50 && event ->x() < 330
    {
        this ->move(event->globalPos() - dragPosition);
        event->accept();
    }
}
//繪製背景
void Music::paintEvent(QPaintEvent *event)
{
    QPainter paint(this);
    QPixmap backgound;
    backgound.load(":/image/music_bg.bmp");
    paint.drawPixmap(0, 0, backgound.width(), backgound.height(),backgound);
    event ->accept();

}

然後寫創建按鈕的函數以及連接槽函數來響應信號的連接語句:

//創建按鈕
void Music::init_controls()
{   
    BtnClose = new QPushButton(this);
    BtnClose -> setObjectName("BtnClose");//如果要對這個對象單獨設stylesheet的話一定要設置它的objectName
    BtnClose -> setGeometry(365,2,30,30);//視窗左上角為原點(X365,Y2),(寬30,高30)
    BtnClose -> setToolTip(tr("退出"));
    BtnClose -> setCursor(QCursor(Qt::PointingHandCursor));//滑鼠指針形狀為手

    BtnMin=new QPushButton(this);
    BtnMin->setObjectName(tr("BtnMin"));
    BtnMin->setGeometry(330,5,25,30);
    BtnMin->setToolTip(tr("最小化"));
    BtnMin->setCursor(QCursor(Qt::PointingHandCursor));

    playPattern=new QPushButton(this);
    /*QIcon icon1(":/image/Seq.png");
    playPattern->setIcon(icon1);*/
    playPattern->setObjectName(tr("playPattern"));
    playPattern->setGeometry(20,255,50,50);
    playPattern->setToolTip(tr("列表迴圈"));
    playPattern->setCursor(QCursor(Qt::PointingHandCursor));


    BtnPlay=new QPushButton(this);
    BtnPlay->setObjectName(tr("BtnPlay"));
    BtnPlay->setGeometry(160,250,56,56);
    BtnPlay->setToolTip(tr("播放"));
    BtnPlay->setCursor(QCursor(Qt::PointingHandCursor));

    BtnPrev=new QPushButton(this);
    BtnPrev->setObjectName(tr("BtnPrev"));
    BtnPrev->setGeometry(120,255,45,45);
    BtnPrev->setToolTip(tr("上一首"));
    BtnPrev->setCursor(QCursor(Qt::PointingHandCursor));

    BtnNext=new QPushButton(this);
    BtnNext->setObjectName(tr("BtnNext"));
    BtnNext->setGeometry(210,255,45,45);
    BtnNext->setToolTip(tr("下一首"));
    BtnNext->setCursor(QCursor(Qt::PointingHandCursor));

    muteButton=new QPushButton(this);
    muteButton->setObjectName(tr("muteButton"));
    muteButton->setGeometry(370,320,25,25);
    muteButton->setToolTip(tr("關閉聲音"));
    muteButton->setCursor(QCursor(Qt::PointingHandCursor));


    volumeControl=new QSlider(Qt::Vertical,this);//QSlider(Qt::Vertical,this)創建一個豎直方向的滑動條QSlider控制項
    volumeControl->setObjectName(tr("volumeControl"));
    volumeControl->setGeometry(375,240,15,80);
    volumeControl->setCursor(QCursor(Qt::PointingHandCursor));
    volumeControl->setRange(0,100);//設置滑動條控制項的最小值和最大值
    volumeControl ->setValue(50);//設置初值為50;

    seekSlider = new QSlider(Qt::Horizontal,this);//QSlider(Qt::Horizontal,this)創建一個水平方向的滑動條QSlider控制項
    seekSlider -> setGeometry(100,345,200,15);
    seekSlider->setObjectName(tr("seekSlider"));
    seekSlider -> setCursor(QCursor(Qt::PointingHandCursor));

    addMore = new QPushButton(this);
    addMore -> setGeometry(295,2,30,30);
    addMore -> setObjectName(tr("addMore"));
    addMore->setToolTip(tr("添加歌曲"));
    addMore -> setCursor(QCursor(Qt::PointingHandCursor));

    showMge = new QLabel(this);
    showMge -> setGeometry(34,320,400,20);
    showMge -> setFont(QFont("Times",10,QFont::Bold));//字體使用Times,10號字體,加粗
    QPalette pac;//創建調色板
    pac.setColor(QPalette::WindowText,QColor(70,80,70));
    showMge -> setPalette(pac);

    list = new QListWidget(this);
    list ->setGeometry(20,50,360,180);
    list -> setFont(QFont("Times",10,QFont::Bold));
    list -> setPalette(pac);
    list ->setStyleSheet("background: rgba(0,0,0,0.1);");


    message = new QLabel(this);
    message -> setGeometry(20,30,140,20);
    message -> setFont(QFont("Times",10,QFont::Bold));
    message -> setPalette(pac);

    showPro = new QLabel(this);
    showPro -> setGeometry(35,340,50,20);
    showPro -> setFont(QFont("Times",10,QFont::Bold));
    showPro -> setPalette(pac);
    QTime mov(0,0,0);
    showPro ->setText(mov.toString("mm:ss"));

    showTime = new QLabel(this);
    showTime -> setGeometry(325,340,50,20);
    showTime -> setFont(QFont("Times",10,QFont::Bold));
    showTime -> setPalette(pac);
    QTime mo(0,0,0);//QTime 提供時間函數給用戶使用
    showTime ->setText(mo.toString("mm:ss"));//顯示分:秒

    title = new QLabel(this);//設置標題
    title -> setGeometry(5,0,200,30);
    title ->setFont(QFont("Times",15,QFont::Bold));
    QPalette pa;
    pa.setColor(QPalette::WindowText,QColor(0,0,0));
    title -> setPalette(pa);
    title -> setText("MusicPlayer");



    //信號與槽
    connect(BtnClose, SIGNAL(clicked(bool)), this, SLOT(close()));
    connect(BtnMin, SIGNAL(clicked(bool)), this, SLOT(showMinimized()));
    connect(addMore, SIGNAL(clicked(bool)), this, SLOT(addMoremusic()));
    connect(BtnPlay, SIGNAL(clicked(bool)), this, SLOT(playMusic()));
    connect (BtnPrev,SIGNAL(clicked(bool)), this, SLOT(preMusic()));
    connect(BtnNext, SIGNAL(clicked(bool)), this, SLOT(nextMusic()));
    connect(muteButton, SIGNAL(clicked(bool)), this, SLOT(meteOpen()));
    connect(volumeControl, SIGNAL(sliderMoved(int)), this, SLOT(volumChange(int)));
    connect(player,SIGNAL(positionChanged(qint64)),this,SLOT( positionChange(qint64)));
    connect(playPattern,SIGNAL(clicked(bool)),this,SLOT(musicPlayPattern()));


}
View Code

但界面很醜,所以下一步就是載入qss文件,繪製界面樣式:

1 //外部載入qss文件,繪製界面樣式
2 void Music::init_skin()
3 {
4     QFile file(":/qss/skin.qss");
5     file.open(QFile::ReadOnly);
6     this -> setStyleSheet(QObject::tr(file.readAll()));
7     file.close();
8 
9 }

我的qss代碼如下(qss和css的語法幾乎一模一樣):

  1 QPushButton#playPattern:!hover
  2 {
  3         border-image: url(:/image/Seq.png);
  4 }
  5 QPushButton#playPattern:hover
  6 {
  7         border-image: url(:/image/Seq.png);
  8 }
  9 QPushButton#playPattern:pressed{
 10         border-image: url(:/image/Seq.png);
 11 }
 12 QPushButton#BtnClose:!hover
 13 {
 14         border-image: url(:/image/close.png);
 15 }
 16 QPushButton#BtnClose:hover
 17 {
 18         border-image: url(:/image/close.png);
 19 }
 20 QPushButton#BtnClose:pressed
 21 {
 22         border-image: url(:/image/close.png);
 23 }
 24 QPushButton#BtnClose:focus{padding:-1;}
 25 
 26 
 27 
 28 QPushButton#addMore
 29 {
 30         border-image: url(:/image/addMore.png);
 31 
 32 }
 33 
 34 
 35 QPushButton#BtnMin:!hover
 36 {
 37         border-image: url(:/image/min.png);
 38 }
 39 QPushButton#BtnMin:hover
 40 {
 41         border-image: url(:/image/min.png);
 42 }
 43 QPushButton#BtnMin:pressed
 44 {
 45         border-image: url(:/image/min.png);
 46 }
 47 QPushButton#BtnMin:focus{padding:-1;}
 48 
 49 
 50 QPushButton#BtnPlay:!hover
 51 {
 52         border-image: url(:/image/play_hover.png);
 53 }
 54 QPushButton#BtnPlay:hover
 55 {
 56         border-image: url(:/image/play_hover.png);
 57 }
 58 QPushButton#BtnPlay:pressed
 59 {
 60         border-image: url(:/image/play_press.png);
 61 }
 62 QPushButton#BtnPlay:focus
 63 {
 64         padding:-1;
 65 }
 66 
 67 QPushButton#BtnPrev:!hover
 68 {
 69         border-image: url(:/image/prev_hover.png);
 70 }
 71 QPushButton#BtnPrev:hover
 72 {
 73         border-image: url(:/image/prev_hover.png);
 74 }
 75 QPushButton#BtnPrev:pressed
 76 {
 77         border-image: url(:/image/prev_press.png);
 78 }
 79 QPushButton#BtnPrev:focus{padding:-1;}
 80 
 81 QPushButton#BtnNext:!hover
 82 {
 83         border-image: url(:/image/next_hover.png);
 84 }
 85 QPushButton#BtnNext:hover
 86 {
 87         border-image: url(:/image/next_hover.png);
 88 }
 89 QPushButton#BtnNext:pressed
 90 {
 91         border-image: url(:/image/next_press.png);
 92 }
 93 QPushButton#BtnNext:focus{padding:-1;}
 94 
 95 
 96 QPushButton#muteButton:!hover
 97 {
 98         border-image: url(:/image/sound.png);
 99  }
100 QPushButton#muteButton:hover
101 {
102         border-image: url(:/image/sound.png);
103 }
104 QPushButton#muteButton:pressed
105 {
106         border-image: url(:/image/sound_close.png);
107 }
108 QPushButton#muteButton:focus{padding:-1;}
109 
110 
111 
112 QSlider#volumeControl::groove:Vertical {
113         border: 0px solid #bbb;
114         background: rgba(0,0,0,0.1);
115         width: 4px;
116         border-radius: 1px;
117 }
118 
119 QSlider#volumeControl::sub-page:Vertical {
120         background: rgba(0,0,0,0.1);
121         border: 0px solid #777;
122         width: 4px;
123         border-radius: 1px;
124 }
125 
126 QSlider#volumeControl::add-page:Vertical {
127         background:url(:/image/progress_sound.bmp);
128         border: 0px solid #777;
129         width: 4px;
130         border-radius: 1px;
131 }
132 
133 QSlider#volumeControl::handle:Vertical {
134         border-image:url(:/image/progress_thume.png);
135         border: 0px solid #777;
136         width: 28px;
137         height: 28px;
138         margin-left:-12px;
139         margin-right:-12px;
140         margin-top: -12px;
141         margin-bottom: -12px;
142         border-radius: 4px;
143 }
144 
145 
146 QSlider#seekSlider::groove:horizontal {
147         border-left:-14px solid;
148         background: rgba(0,0,0,0.1);
149         height: 4px;
150         border-radius: 4px;
151 }
152 
153 QSlider#seekSlider::sub-page:horizontal {
154         background:url(:/image/progress.bmp);
155         border: 0px solid #777;
156         height: 4px;
157         border-radius: 4px;
158 }
159 
160 QSlider#seekSlider::add-page:horizontal {
161         background: rgba(0,0,0,0.1);
162         border: 0px solid #777;
163         height: 4px;
164         border-radius:4px;
165 }
166 
167 QSlider#seekSlider::handle:horizontal {
168         background:url(:/image/progress_thume.png);
169         border: 0px solid #777;
170         width: 28px;
171         height: 28px;
172         border-left:0px;
173         border-right:0px;
174         margin-left:2px;
175         margin-right:-12px;
176         margin-top: -12px;
177         margin-bottom: -12px;
178         border-radius: 4px;
179 }
View Code

這樣樣式就已經基本搞定了,只剩下寫槽函數來實現具體功能了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. Ubuntu16.04上使用sudo apt-get install php7.1 安裝php的預設路徑如下: a. php可執行命令:/usr/bin/php7.1 和 /usr/bin/php b. 需要安裝sudo apt install php7.1-dev 才會有 /usr/bin/ ...
  • 導讀: 1.變數和對象 2.可變對象與不可變對象 3.引用傳參 在C/C++中,傳值和傳引用是函數參數傳遞的兩種方式。由於思維定式,從C/C++轉過來的Python初學者也經常會感到疑惑:在Python中,函數參數傳遞是傳值,還是傳引用呢?看下麵兩段代碼: 看完第一段代碼,會有人說這是值傳遞,因為函 ...
  • Q: 棧、隊列與數組的區別? A: 本篇主要涉及三種數據存儲類型:棧、隊列和優先順序隊列,它與數組主要有如下三個區別: A: (一)程式員工具 數組和其他的結構(棧、隊列、鏈表、樹等等)都適用於資料庫應用中作為數據記錄。它們常用於記錄那些對應於現實世界的對象和活動的數據,如職員檔案等,這些結構便於數據 ...
  • 判斷cookie是否為空非常重要,因為第一次訪問的時候為空會發生空指針異常。 註意對request和response的亂碼問題進行處理 註意連接c3p0時需要的jar包、工具類以及配置文件 ...
  • 傳說學java的圈子裡面存在著這樣一個鄙視鏈:電腦專業科班出身的鄙視自學java的,自學java的鄙視參加java培訓的。主要是他們覺得明明現在互聯網這麼發達,網上到處都是java學習資料,比如各種免費的java視頻教程、書籍,去參加java培訓班簡直就是浪費錢嘛!但為什麼還是有那麼多人要去參加j ...
  • 最近寫了一個爬蟲,需要連接國外的一個網站,經常出現掉線的情況,自己寫了一個自動重連的代碼,但感覺不夠簡潔。。。 後來就上萬能的github,找到了一個第三包,基本能滿足我的要求。這個第三方包就是retrying. 我的需求就是每當出現request相關異常的時候,就自動重來,上限連接10次;使用代碼 ...
  • 今天想自己搭一個blog網站,由於之前一直使用Java開發伺服器,並且使用的是nginx,所以沒有搭建PHP的運行環境。於是決定寫下這篇博文與大家一起分享一下。 先介紹一下使用的環境:centos 7.4, PHP 7.0 , nginx 1.12 不同的系統版本可能配置有些稍微不同,請大家配置的時 ...
  • 封裝性(有時稱為數據隱藏)。實現封裝的關鍵在於絕對不能讓類中的方法直接地訪問其他類的實例域值。程式僅通過對象的方法與對象的數據進行交互。給對象賦予了“黑盒”的特征,提高了重用性和可靠性。簡而言之,就是只需知道方法對應的作用,而不必瞭解它的具體實現過程。 實例域 私有數據域即寫在全局的私有變數或常量。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...