基于Qt的MP3播放器的设计与实现

项目描述:QT开发的一个MP3播放器。基本实现功能包括:上一首、播放/暂停、停止、下一首、文件打开、歌词同步显示、播放列表的显示、显示到托盘等功能。

项目代码如下:

widget.h

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include 
 5 #include 
 6 #include 
 7 
 8 #include 
 9 #include 
10 #include 
11 
12 namespace Ui {
13     class Widget;
14 }
15 
16 class Widget : public QWidget
17 {
18     Q_OBJECT
19 
20 public:
21     explicit Widget(QWidget *parent = 0);
22     ~Widget();
23     void creatActions();//创建动作
24 
25 private slots:
26     void on_toolButton_previous_clicked();//上一首
27     void on_toolButton_playpause_clicked();//播放/暂停
28     void on_toolButton_stop_clicked();//停止播放
29     void on_toolButton_next_clicked();//下一首
30     void on_toolButton_open_clicked();//打开
31 
32 private:
33     Ui::Widget *ui;
34     Phonon::MediaObject *mediaObject;//管理媒体源
35     Phonon::MediaObject *musicInformationMediaObject;//
36     Phonon::VideoWidget *videoWidget;//
37     Phonon::AudioOutput *audioOutput;//连接物理设备
38     Phonon::SeekSlider *seekSlider;//实现进度条
39     Phonon::VolumeSlider *volumeSlider;//音量调节
40     QList musicSourceList;//播放列表
41 
42     QTimer *timer;
43 
44     QIcon *iconplay;
45     QIcon *iconpause;
46 
47     QAction *play;
48     QAction *stop;
49     QAction *open;
50     QAction *exit;
51 
52 public:
53     void setCurrentLrc();//设置歌词显示
54 
55 private slots:
56     void listWidget_cellDoubleClicked(QModelIndex);//双击选歌
57     void showTime(qint64);//时间更新显示
58     void mediaObjectStateChanged(Phonon::State,Phonon::State);
59     void musicAboutToFinish();//歌曲快结束时
60     void currentMusicSourceChanged(Phonon::MediaSource);
61     void musicInformationStateChanged(Phonon::State,Phonon::State);
62     void exitSlot();
63     void iconActivated(QSystemTrayIcon::ActivationReason);
64 
65 private:
66     QTextEdit *text;//解析歌词
67     QSystemTrayIcon *trayicon;
68     QMenu *trayiconMenu;
69 
70 protected:
71     void keyPressEvent(QKeyEvent *);
72     void dragEnterEvent(QDragEnterEvent *);
73     void dropEvent(QDropEvent *);//拖放歌曲
74 };
75 
76 #endif // WIDGET_H

 

wdget.cpp

  1 #include 
  2 #include 
  3 #include 
  4 #include 
  5 #include 
  6 #include 
  7 
  8 #include "widget.h"
  9 #include "ui_widget.h"
 10 
 11 Widget::Widget(QWidget *parent) :
 12     QWidget(parent),
 13     ui(new Ui::Widget)
 14 {
 15     ui->setupUi(this);
 16 
 17     this->setWindowTitle(tr("MP3播放器"));//设置标题
 18     this->setMouseTracking(true);//启用widget的鼠标跟踪。
 19 
 20     /**初始化媒体**/
 21     mediaObject =new Phonon::MediaObject();//媒体对象
 22     mediaObject->setTickInterval(1);
 23     audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory);//音频输出
 24     Phonon::createPath(mediaObject,audioOutput);//连接媒体对象与音频输出
 25 
 26     musicInformationMediaObject = new Phonon::MediaObject(this);  //音乐信息对象
 27 
 28     volumeSlider = new Phonon::VolumeSlider(audioOutput,this);  //音量滑动条
 29     volumeSlider->move(220,70);
 30     volumeSlider->resize(50,20);
 31     volumeSlider->setStyleSheet("background-color:rgb(255,255,255,100)");
 32     volumeSlider->setFixedWidth(100);//固定音量条大小
 33 
 34     seekSlider = new Phonon::SeekSlider(mediaObject,this); //进度滑动条
 35     seekSlider->move(10,35);
 36     seekSlider->resize(170,20);
 37     seekSlider->setStyleSheet("background-color:rgb(255,255,255,100)");
 38 
 39     creatActions();
 40 
 41     connect(mediaObject,SIGNAL(tick(qint64)),this,SLOT(showTime(qint64)));
 42     //时间显示与歌词的更新,tick发射媒体对象流的时间参数,单位毫秒
 43     connect(mediaObject,SIGNAL(stateChanged(Phonon::State,Phonon::State)),this,SLOT(mediaObjectStateChanged(Phonon::State,Phonon::State)));
 44 
 45     text = new QTextEdit(this);
 46     text->hide();//用于查找下句歌词以计算时间间隔
 47     ui->textEdit->setVisible(false);//文本编辑框不可见,(解析歌词)
 48     connect(ui->listWidget,SIGNAL(doubleClicked(QModelIndex)),SLOT(listWidget_cellDoubleClicked(QModelIndex)));
 49     //双击播放歌曲
 50     connect(musicInformationMediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),this, SLOT(musicInformationStateChanged(Phonon::State,Phonon::State)));
 51     //当加入新音乐时执行
 52     //自动播放下一首
 53     connect(mediaObject,SIGNAL(aboutToFinish()),this,SLOT(musicAboutToFinish()));//本首音乐快结束时
 54     connect(mediaObject,SIGNAL(currentSourceChanged(Phonon::MediaSource)),this,SLOT(currentMusicSourceChanged(Phonon::MediaSource)));
 55 
 56     QPalette palette = ui->label_lrc->palette();//设置窗体内歌词颜色
 57     palette.setColor(QPalette::WindowText,Qt::darkBlue);
 58     ui->label_lrc->setPalette(palette);
 59 
 60     setWindowIcon(QIcon(":/images/blank.png"));
 61     setAutoFillBackground(true);
 62 
 63     ui->listWidget->setStyleSheet("background:rgb(255,255,255,0,)");
 64     seekSlider->setToolTip(tr("播放进度条"));//鼠标停留显示 setAcceptDrops(true);
 65     setAcceptDrops(true);
 66 }
 67 
 68 Widget::~Widget()
 69 {
 70     delete ui;
 71 }
 72 
 73 void Widget::exitSlot()//托盘菜单的关闭
 74 {
 75     this->hide();
 76     this->close();
 77 }
 78 
 79 //上一首
 80 void Widget::on_toolButton_previous_clicked()
 81 {
 82     int index = musicSourceList.indexOf(mediaObject->currentSource()) - 1;
 83     if(index >= 0)
 84     {
 85         mediaObject->stop();
 86         mediaObject->setCurrentSource(musicSourceList.at(index));
 87         mediaObject->play();
 88     }
 89     else
 90     {
 91         QMessageBox::information(this, tr("警告"), tr("没有上一首歌曲"));
 92         return;
 93     }
 94 }
 95 
 96 //播放/暂停
 97 void Widget::on_toolButton_playpause_clicked()
 98 {
 99     if(musicSourceList.isEmpty())
100     {
101         QMessageBox::information(this, tr("警告"), tr("没有歌曲"));
102         return ;
103     }
104     mediaObject->setQueue(musicSourceList);//列表循环
105 
106     if(mediaObject->state() == Phonon::PlayingState)
107         mediaObject->pause();
108     else
109     {
110         mediaObject->play();
111     }
112 }
113 
114 //停止播放
115 void Widget::on_toolButton_stop_clicked()
116 {
117     mediaObject->stop();
118 }
119 
120 //下一首
121 void Widget::on_toolButton_next_clicked()
122 {
123     int index = musicSourceList.indexOf(mediaObject->currentSource()) + 1;
124     if(index < musicSourceList.size())
125     {
126         mediaObject->stop();
127         mediaObject->setCurrentSource(musicSourceList.at(index));
128         mediaObject->play();
129     }
130     else
131     {
132          QMessageBox::information(this, tr("警告"), tr("没有下一首歌曲"));
133          return;
134     }
135 
136 }
137 
138 void Widget::on_toolButton_open_clicked()
139 {
140     QStringList list = QFileDialog::getOpenFileNames(this,tr("打开音乐文件"),QDesktopServices::storageLocation(QDesktopServices::MusicLocation),tr("Music (*.mp3 *.wma)"));
141     if(list.isEmpty())
142         return;
143     int index = musicSourceList.size();  //获取当前列表的长度
144     foreach(QString string,list)
145     {
146         Phonon::MediaSource source(string);
147         musicSourceList.append(source);//在当前列表后加入一条记录
148     }
149     if(!musicSourceList.isEmpty())
150         musicInformationMediaObject->setCurrentSource(musicSourceList.at(index));
151 
152     //将新加入的第一条记录添加到musicInformationMediaObject
153     ui->listWidget->clear();
154     index = musicSourceList.size();  //获取当前列表的长度
155     for(int i = 0; i < index; i++)
156     {
157         musicInformationMediaObject->setCurrentSource(musicSourceList.at(i));
158         QString fileName = musicInformationMediaObject->currentSource().fileName();
159         QString mp3Name = fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1);
160         ui->listWidget->addItem(mp3Name);
161         //qDebug()<
162     }
163 }
164 
165 void Widget::creatActions()
166 {
167     QIcon iconstop(":/images/gtk-media-stop.png");
168     QIcon iconopen(":/images/gtk-open.png");
169     QIcon iconexit(":/images/exit.png");
170     iconpause = new QIcon(":/images/gtk-media-pause.png");
171     iconplay = new QIcon(":/images/gtk-media-play-ltr.png");
172 
173     play = new QAction(*iconplay,tr("播放"),this);
174     connect(play,SIGNAL(triggered()),this,SLOT(on_toolButton_playpause_clicked()));
175 
176     stop = new QAction(iconstop,tr("停止"),this);
177     connect(stop,SIGNAL(triggered()),mediaObject,SLOT(stop()));
178 
179     open = new QAction(iconopen,tr("打开文件"),this);
180     connect(open,SIGNAL(triggered()),this,SLOT(on_toolButton_open_clicked()));
181 
182     exit = new QAction(iconexit,tr("退出"),this);
183     connect(exit,SIGNAL(triggered()),this,SLOT(exitSlot()));
184 
185     /***系统托盘****/
186     trayicon = new QSystemTrayIcon(this);
187     QIcon ico(":/images/icon.ico.png");
188     trayiconMenu = new QMenu(this);
189     trayiconMenu->addAction(play);
190     trayiconMenu->addAction(stop);
191     trayiconMenu->addAction(open);
192     trayiconMenu->addSeparator();
193     trayiconMenu->addAction(exit);
194 
195     trayicon->setIcon(ico);
196     trayicon->setToolTip(tr("正在播放:"));
197     trayicon->setContextMenu(trayiconMenu);
198 
199     trayicon->show();
200     trayicon->showMessage(tr("MP3播放器"),tr("计算机091 黄华"),QSystemTrayIcon::Information,10000);
201 
202     connect(trayicon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));//图标被激活时
203 }
204 
205 void Widget::iconActivated(QSystemTrayIcon::ActivationReason reason)
206 {
207     switch(reason)
208     {
209     case QSystemTrayIcon::Trigger://单击
210     case QSystemTrayIcon::DoubleClick://双击
211         this->setWindowState(Qt::WindowActive);//恢复窗口显示
212         this->show();
213         break;
214     case QSystemTrayIcon::MiddleClick:
215         trayicon->showMessage(tr("音乐播放器"),tr("计算机091 黄华"),QSystemTrayIcon::Information,10000);
216         break;
217     default:
218         ;
219     }
220 }
221 
222 void Widget::listWidget_cellDoubleClicked(QModelIndex index)
223 {
224     mediaObject->stop();
225     mediaObject->clearQueue();
226     int row = index.row();
227     if (row >= musicSourceList.size())
228         return;
229     mediaObject->setCurrentSource(musicSourceList[row]);
230     mediaObject->play();
231 }
232 
233 void Widget::showTime(qint64 time)//时间与歌词的更新显示
234 {
235     qint64 temp = mediaObject->totalTime();
236     QTime totalTime(0,(temp / 60000) % 60,(temp / 1000) % 60,time %1000);//(h,min,s,ms)
237     QTime curTime(0,(time / 60000) % 60,(time / 1000) % 60,time %1000);
238     ui->label_time->setText(tr("%1 / %2").arg(curTime.toString("mm:ss")).arg(totalTime.toString("mm:ss")));
239     ui->label_time->update();
240 
241     /**歌词的更新显示**/
242     if(ui->textEdit->find(curTime.toString("mm:ss.zzz").left(7)))//向后找
243     {
244         QString str = ui->textEdit->textCursor().block().text().replace(QRegExp("\\[\\d{2}:\\d{2}\\.\\d{2}\\]"),"");
245         ui->label_lrc->setText(str);
246 
247         QTime tt = curTime;
248         int b = 1;
249         int c= 0;
250         text->setText(ui->textEdit->document()->toPlainText());
251         bool over = ui->textEdit->textCursor().block().next().text().isEmpty();
252         while(!over &&!text->find(tt.addMSecs(b*100).toString("mm:ss.zzz").left(7)))
253         {
254             b++;
255             c++;
256         }
257         while(over && !text->find(tt.addMSecs(b*100).toString("mm:ss.zzz").left(7),QTextDocument::FindBackward))
258         {
259             b++;
260             c++;
261             break;
262         }
263 
264     }//找不到后向前找
265     else if(ui->textEdit->find(curTime.toString("mm:ss.zzz").left(7),QTextDocument::FindBackward))
266     {
267         QString str = ui->textEdit->textCursor().block().text().replace(QRegExp("\\[\\d{2}:\\d{2}\\.\\d{2}\\]"),"");
268         ui->label_lrc->setText(str);
269 
270         QTime tt = curTime;
271         int b = 1;
272         int c= 0;
273         text->setText(ui->textEdit->document()->toPlainText());
274 
275         bool over = ui->textEdit->textCursor().block().next().text().isEmpty();
276         while(!over && !text->find(tt.addMSecs(b*100).toString("mm:ss.zzz").left(7)))
277         {
278             b++;
279             c++;
280         }
281         while(over && !text->find(tt.addMSecs(b*100).toString("mm:ss.zzz").left(7),QTextDocument::FindBackward))
282         {
283             b++;
284             c++;
285             break;
286         }
287     }
288 }
289 
290 void Widget::mediaObjectStateChanged(Phonon::State, Phonon::State)
291 {
292     switch(mediaObject->state())
293     {
294     case Phonon::PlayingState:
295         {
296             ui->label_lrc->setText("Music ...");
297             setCurrentLrc();//打开歌词文件
298             play->setIcon(*iconpause);//图标改为“暂停”
299             ui->toolButton_playpause->setIcon(*iconpause);
300             ui->toolButton_playpause->setToolTip(tr("暂停"));
301             play->setText(tr("暂停"));
302             QString fileName = mediaObject->currentSource().fileName();
303             QString title = fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1);
304             this->setWindowTitle(title);//显示“*.mp3”
305             ui->label_palyname->setText(title);
306             trayicon->setToolTip(tr("正在播放:")+ title);
307             break;
308         }
309     case Phonon::PausedState:
310         {
311             play->setIcon(*iconplay);
312             ui->toolButton_playpause->setIcon(*iconplay);
313             ui->toolButton_playpause->setToolTip(tr("播放"));
314             ui->label_palyname->setText(tr("暂停"));
315             play->setText(tr("播放"));
316             trayicon->setToolTip(tr("暂停"));
317             break;
318         }
319     case Phonon::StoppedState:
320         {
321             ui->toolButton_playpause->setIcon(*iconplay);
322             play->setText(tr("播放"));
323             play->setIcon(*iconplay);
324             this->setWindowTitle(tr("MP3播放器"));
325             ui->label_palyname->setText(tr("停止"));
326             trayicon->setToolTip(tr("停止"));
327             ui->label_time->setText("00:00 / 00:00");
328             ui->label_lrc->setText("Music ...");
329             break;
330         }
331 
332     case Phonon::LoadingState:
333         break;
334     case Phonon::ErrorState:
335         break;
336     case Phonon::BufferingState://缓冲状态
337         break;
338     }
339 }
340 
341 void Widget::setCurrentLrc()//设置当前歌词显示
342 {
343     QString fileName = mediaObject->currentSource().fileName();
344 
345     QString lrcName = fileName.remove(fileName.right(3)) + "lrc"; //将"*.mp3"改为“*.lrc”
346     QFile file(lrcName);
347     if(!file.open(QFile::ReadOnly | QFile::Text))
348     {
349         ui->label_lrc->setText(tr("未找到歌词文件"));
350     }
351     QTextStream in(&file);
352     ui->textEdit->setText(in.readAll());//将所有歌词写入textEdit,但textEdit是隐藏的,因此界面看不到
353 }
354 
355 void Widget::musicAboutToFinish() //本首音乐快结束时
356 {
357     int index = musicSourceList.indexOf(mediaObject->currentSource()) + 1; //下一首
358     if(musicSourceList.size() > index)
359         mediaObject->enqueue(musicSourceList.at(index));//注意:不会产生状态的改变state
360     else
361         mediaObject->stop();
362 }
363 
364 void Widget::currentMusicSourceChanged(Phonon::MediaSource source)//当自动播放下一曲音乐时,在listWidget中让它为选中状态
365 {
366     ui->listWidget->setCurrentRow(musicSourceList.indexOf(source), QItemSelectionModel::ToggleCurrent);
367     setCurrentLrc();
368     QString fileName = mediaObject->currentSource().fileName();
369     QString title = fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1);
370     this->setWindowTitle(title);//显示“*.mp3”
371     ui->label_palyname->setText(title);
372     mediaObject->pause();//在此改变一下状态触发mediaObjectStateChanged槽函数
373     mediaObject->play();
374 }
375 
376 void Widget::keyPressEvent(QKeyEvent *key)
377 {
378     QString str="   ";
379     switch(key->modifiers())
380     {
381     case Qt::ShiftModifier:
382         str += "Shift+";
383         break;
384     case Qt::ControlModifier:
385         str += "Control+";
386         break;
387     case Qt::AltModifier:
388         str += "Alt+";
389         break;
390     default:
391         break;
392     }
393     switch(key->key())
394     {
395     case Qt::Key_Up:
396         str += "Up";
397         break;
398     case Qt::Key_Down:
399         str += "Down";
400         break;
401     case Qt::Key_Right:
402         str += "Right";
403         on_toolButton_next_clicked();
404         break;
405     case Qt::Key_Left:
406         str += "Left";
407         on_toolButton_previous_clicked();//上一首
408         break;
409     default:
410         break;
411     }
412 }
413 
414 void Widget::musicInformationStateChanged(Phonon::State newState,Phonon::State)
415 {
416     if (newState != Phonon::StoppedState && newState != Phonon::PausedState)
417         return;  //必须加入这句,不然歌曲列表中可能出现重复歌曲
418     if (musicInformationMediaObject->currentSource().type() == Phonon::MediaSource::Invalid)
419             return;
420     QMap metaData = musicInformationMediaObject->metaData();
421     QString fileName = musicInformationMediaObject->currentSource().fileName();
422     QString mp3Name = fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1);
423     ui->listWidget->addItem(mp3Name);
424 
425     int index = musicSourceList.indexOf(musicInformationMediaObject->currentSource()) + 1;
426     if (musicSourceList.size() > index) //如果还未处理完
427     {
428      musicInformationMediaObject->setCurrentSource(musicSourceList.at(index));
429      //处理下一首歌曲
430      if (musicInformationMediaObject->currentSource().type() == Phonon::MediaSource::Invalid)
431          musicInformationMediaObject->setCurrentSource(musicSourceList.at(index+1));
432     }
433     if(mediaObject->state() != Phonon::PlayingState)//打开后播放
434     {
435         on_toolButton_playpause_clicked();
436     }
437 }
438 
439 void Widget::dragEnterEvent(QDragEnterEvent *event)
440 {
441     if (event->mimeData()->hasFormat("text/uri-list"))
442         event->acceptProposedAction();
443 }
444 
445 void Widget::dropEvent(QDropEvent *event)
446 {
447     QList urls = event->mimeData()->urls();
448     if (urls.isEmpty())
449     {
450         return;
451     }
452     QString fileName = urls.first().toLocalFile();
453     if (fileName.isEmpty())
454     {
455         return;
456     }
457     int index = musicSourceList.size();  //获取当前列表的长度
458     for(int i=0; i)
459     {
460         QString string = urls.at(i).toString();
461         Phonon::MediaSource source(string);
462         musicSourceList.append(source);//在当前列表后加入一条记录
463     }
464 
465     if(!musicSourceList.isEmpty())
466        musicInformationMediaObject->setCurrentSource(Phonon::MediaSource(musicSourceList.at(index)));
467 }

 

main.cpp

 1 #include 
 2 #include 
 3 #include "widget.h"
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     QApplication a(argc, argv);
 8     a.setApplicationName("MP3");
 9     QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
10     Widget w;
11     w.show();
12 
13     return a.exec();
14 }

 

 

转载于:https://www.cnblogs.com/luciaark/archive/2013/06/06/Phonon.html

你可能感兴趣的:(基于Qt的MP3播放器的设计与实现)