├── HiLogo4.ico ├── HiPlayer_test.pro ├── HiPlayer_test.pro.user ├── aboutDialog.cpp ├── aboutDialog.h ├── hiButton.cpp ├── hiButton.h ├── hiLabel.cpp ├── hiLabel.h ├── hiLrcWidget.cpp ├── hiLrcWidget.h ├── hiVolBotton.cpp ├── hiVolBotton.h ├── hiplayer.cpp ├── hiplayer.h ├── icon.qrc ├── lrcLabel.cpp ├── lrcLabel.h ├── main.cpp ├── miniWindow.cpp ├── miniWindow.h ├── network.cpp ├── network.h ├── nofocusdelegate.cpp ├── nofocusdelegate.h ├── playslider.cpp ├── playslider.h ├── readme.md ├── resources ├── HiLogo.png ├── HiLogo4.ico ├── HiLogo_2.ico ├── HiPlayer_16_16_2.png ├── HiPlayer_256_256_2.png ├── HiPlayer_32_32_2.png ├── HiPlayer_38_38.png ├── HiPlayer_48_48_2.png ├── HiPlayer_80_80_2.png ├── Last_40_40.png ├── Lyric_40_40.png ├── Next_40_40.png ├── Pause_100_100.png ├── Pause_60_60.png ├── Play_100_100.png ├── Play_60_60.png ├── Volumn_40_40.png ├── about.png ├── addMusic_40_40.png ├── album.png ├── background.png ├── default_album.jpg ├── last_mini.png ├── lrc_background.png ├── max_mini.png ├── mini_back.png ├── mode.png ├── next_mini.png ├── pause_mini.png ├── play_mini.png ├── 关闭.png ├── 播放按钮mini.png ├── 最小化.png └── 缩小.png ├── singleApp.cpp ├── singleApp.h └── songinfo.h /HiLogo4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/HiLogo4.ico -------------------------------------------------------------------------------- /HiPlayer_test.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2017-12-19T16:32:58 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui network multimedia 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = HiPlayer 12 | TEMPLATE = app 13 | 14 | #RC_ICONS = logo.ico 15 | RC_ICONS = HiLogo4.ico 16 | CONFIG += c++11 17 | # The following define makes your compiler emit warnings if you use 18 | # any feature of Qt which as been marked as deprecated (the exact warnings 19 | # depend on your compiler). Please consult the documentation of the 20 | # deprecated API in order to know how to port your code away from it. 21 | DEFINES += QT_DEPRECATED_WARNINGS 22 | 23 | # You can also make your code fail to compile if you use deprecated APIs. 24 | # In order to do so, uncomment the following line. 25 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 26 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 27 | 28 | 29 | SOURCES += main.cpp\ 30 | hiButton.cpp \ 31 | aboutDialog.cpp \ 32 | hiLabel.cpp \ 33 | lrcLabel.cpp \ 34 | hiLrcWidget.cpp \ 35 | hiVolBotton.cpp \ 36 | singleApp.cpp \ 37 | nofocusdelegate.cpp \ 38 | network.cpp \ 39 | hiplayer.cpp \ 40 | miniWindow.cpp \ 41 | playslider.cpp 42 | 43 | HEADERS += \ 44 | hiButton.h \ 45 | aboutDialog.h \ 46 | hiLabel.h \ 47 | lrcLabel.h \ 48 | hiLrcWidget.h \ 49 | hiVolBotton.h \ 50 | singleApp.h \ 51 | songinfo.h \ 52 | nofocusdelegate.h \ 53 | network.h \ 54 | hiplayer.h \ 55 | miniWindow.h \ 56 | playslider.h 57 | 58 | RESOURCES += \ 59 | icon.qrc 60 | -------------------------------------------------------------------------------- /HiPlayer_test.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {2ded4aa9-436d-4906-a6f4-6cd40ced68f4} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | 60 | ProjectExplorer.Project.Target.0 61 | 62 | Desktop Qt 5.8.0 MinGW 32bit 63 | Desktop Qt 5.8.0 MinGW 32bit 64 | qt.58.win32_mingw53_kit 65 | 0 66 | 0 67 | 0 68 | 69 | I:/HiPlayer/build-HiPlayer-Desktop_Qt_5_8_0_MinGW_32bit-Debug 70 | 71 | 72 | true 73 | qmake 74 | 75 | QtProjectManager.QMakeBuildStep 76 | true 77 | 78 | false 79 | false 80 | false 81 | 82 | 83 | true 84 | Make 85 | 86 | Qt4ProjectManager.MakeStep 87 | 88 | false 89 | 90 | 91 | 92 | 2 93 | 构建 94 | 95 | ProjectExplorer.BuildSteps.Build 96 | 97 | 98 | 99 | true 100 | Make 101 | 102 | Qt4ProjectManager.MakeStep 103 | 104 | true 105 | clean 106 | 107 | 108 | 1 109 | 清理 110 | 111 | ProjectExplorer.BuildSteps.Clean 112 | 113 | 2 114 | false 115 | 116 | Debug 117 | 118 | Qt4ProjectManager.Qt4BuildConfiguration 119 | 2 120 | true 121 | 122 | 123 | I:/HiPlayer/HiPlayer_test/build-HiPlayer_test-Desktop_Qt_5_8_0_MinGW_32bit-Release 124 | 125 | 126 | true 127 | qmake 128 | 129 | QtProjectManager.QMakeBuildStep 130 | false 131 | 132 | false 133 | false 134 | false 135 | 136 | 137 | true 138 | Make 139 | 140 | Qt4ProjectManager.MakeStep 141 | 142 | false 143 | 144 | 145 | 146 | 2 147 | 构建 148 | 149 | ProjectExplorer.BuildSteps.Build 150 | 151 | 152 | 153 | true 154 | Make 155 | 156 | Qt4ProjectManager.MakeStep 157 | 158 | true 159 | clean 160 | 161 | 162 | 1 163 | 清理 164 | 165 | ProjectExplorer.BuildSteps.Clean 166 | 167 | 2 168 | false 169 | 170 | Release 171 | 172 | Qt4ProjectManager.Qt4BuildConfiguration 173 | 0 174 | true 175 | 176 | 177 | I:/HiPlayer/HiPlayer_test/build-HiPlayer_test-Desktop_Qt_5_8_0_MinGW_32bit-Profile 178 | 179 | 180 | true 181 | qmake 182 | 183 | QtProjectManager.QMakeBuildStep 184 | true 185 | 186 | false 187 | true 188 | false 189 | 190 | 191 | true 192 | Make 193 | 194 | Qt4ProjectManager.MakeStep 195 | 196 | false 197 | 198 | 199 | 200 | 2 201 | 构建 202 | 203 | ProjectExplorer.BuildSteps.Build 204 | 205 | 206 | 207 | true 208 | Make 209 | 210 | Qt4ProjectManager.MakeStep 211 | 212 | true 213 | clean 214 | 215 | 216 | 1 217 | 清理 218 | 219 | ProjectExplorer.BuildSteps.Clean 220 | 221 | 2 222 | false 223 | 224 | Profile 225 | 226 | Qt4ProjectManager.Qt4BuildConfiguration 227 | 0 228 | true 229 | 230 | 3 231 | 232 | 233 | 0 234 | 部署 235 | 236 | ProjectExplorer.BuildSteps.Deploy 237 | 238 | 1 239 | 在本地部署 240 | 241 | ProjectExplorer.DefaultDeployConfiguration 242 | 243 | 1 244 | 245 | 246 | false 247 | false 248 | 1000 249 | 250 | true 251 | 252 | false 253 | false 254 | false 255 | false 256 | true 257 | 0.01 258 | 10 259 | true 260 | 1 261 | 25 262 | 263 | 1 264 | true 265 | false 266 | true 267 | valgrind 268 | 269 | 0 270 | 1 271 | 2 272 | 3 273 | 4 274 | 5 275 | 6 276 | 7 277 | 8 278 | 9 279 | 10 280 | 11 281 | 12 282 | 13 283 | 14 284 | 285 | 2 286 | 287 | HiPlayer_test 288 | 289 | Qt4ProjectManager.Qt4RunConfiguration:I:/HiPlayer/HiPlayer/HiPlayer_test.pro 290 | true 291 | 292 | HiPlayer_test.pro 293 | false 294 | 295 | I:/HiPlayer/build-HiPlayer-Desktop_Qt_5_8_0_MinGW_32bit-Debug 296 | 3768 297 | false 298 | true 299 | false 300 | false 301 | true 302 | 303 | 1 304 | 305 | 306 | 307 | ProjectExplorer.Project.TargetCount 308 | 1 309 | 310 | 311 | ProjectExplorer.Project.Updater.FileVersion 312 | 18 313 | 314 | 315 | Version 316 | 18 317 | 318 | 319 | -------------------------------------------------------------------------------- /aboutDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "aboutDialog.h" 2 | #include "hiButton.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | AboutDialog::AboutDialog(QWidget *parent) 12 | :QDialog(parent) 13 | ,m_Moveing(false) 14 | { 15 | m_exitButton = new HiButton(this); 16 | m_exitButton->setObjectName(QStringLiteral("exitButton")); 17 | m_exitButton->setGeometry(QRect(240, 14, 30, 30)); 18 | QIcon icon_exit, icon_exit_focus; 19 | icon_exit.addFile(QStringLiteral(":/hiplayer/resources/关闭.png"), QSize(), QIcon::Normal, QIcon::Off); 20 | icon_exit_focus.addFile(QStringLiteral(":/hiplayer/resources/关闭按钮.png"), QSize(), QIcon::Normal, QIcon::Off); 21 | m_exitButton->hi_setButtonIcons(icon_exit, icon_exit); 22 | 23 | m_exitButton->setIconSize(QSize(20,20)); 24 | m_exitButton->setFlat(true); 25 | m_exitButton->setFocusPolicy(Qt::NoFocus); 26 | //RGB(255,255,255)表示白色.基本语法:{color: Rgba (red, green, blue, opacity)} 27 | m_exitButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 28 | 29 | connect(m_exitButton, SIGNAL(clicked()), this, SLOT(close())); 30 | 31 | //去除标题栏,需要自定义窗口的拖动 32 | this->setWindowFlags(Qt::FramelessWindowHint); 33 | 34 | //设置窗体背景透明,配合paintEvent设置不规则背景图 35 | setAttribute(Qt::WA_TranslucentBackground); 36 | 37 | //半透明 38 | this->setWindowOpacity(0.9); 39 | 40 | //固定大小 41 | this->setFixedSize(290, 310); 42 | 43 | //模态窗口(即弹出后无法点击主界面) 44 | this->setModal(true); 45 | } 46 | 47 | void AboutDialog::paintEvent(QPaintEvent * ) 48 | { 49 | QPainter p(this); 50 | p.drawPixmap(0, 0 , QPixmap(":/hiplayer/resources/about.png")); 51 | } 52 | 53 | AboutDialog::~AboutDialog() 54 | {} 55 | 56 | void AboutDialog::mousePressEvent(QMouseEvent *event) 57 | { 58 | m_Moveing=true; 59 | //记录下鼠标相对于窗口的位置 60 | //event->globalPos()鼠标按下时,鼠标相对于整个屏幕位置 61 | //pos() this->pos()鼠标按下时,窗口相对于父窗口的位置 62 | m_MovePosition=event->globalPos() - pos(); 63 | return QDialog::mousePressEvent(event); 64 | } 65 | 66 | void AboutDialog::mouseMoveEvent(QMouseEvent *event) 67 | { 68 | //(event->buttons() && Qt::LeftButton)按下是左键 69 | //鼠标移动事件需要移动窗口,窗口移动到哪里呢?就是要获取鼠标移动中,窗口在整个屏幕的坐标,然后move到这个坐标,怎么获取坐标? 70 | //通过事件event->globalPos()知道鼠标坐标,鼠标坐标减去鼠标相对于窗口位置,就是窗口在整个屏幕的坐标 71 | if (m_Moveing && (event->buttons() && Qt::LeftButton) 72 | && (event->globalPos()-m_MovePosition).manhattanLength() > QApplication::startDragDistance()) 73 | { 74 | move(event->globalPos()-m_MovePosition);//相对于桌面的位置. 75 | m_MovePosition = event->globalPos() - pos(); 76 | } 77 | return QDialog::mouseMoveEvent(event); 78 | } 79 | 80 | void AboutDialog::mouseReleaseEvent(QMouseEvent *) 81 | { 82 | m_Moveing=false; 83 | } 84 | -------------------------------------------------------------------------------- /aboutDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef ABOUT_H 2 | #define ABOUT_H 3 | 4 | #include 5 | #include 6 | 7 | class HiButton; 8 | 9 | class AboutDialog : public QDialog 10 | { 11 | Q_OBJECT 12 | public: 13 | AboutDialog(QWidget *parent = 0); 14 | ~AboutDialog(); 15 | 16 | 17 | protected: 18 | void paintEvent(QPaintEvent *event); //用窗口绘制事件来绘制背景图片 19 | 20 | void mousePressEvent(QMouseEvent *event); 21 | void mouseMoveEvent(QMouseEvent *event); 22 | void mouseReleaseEvent(QMouseEvent *event); 23 | private slots: 24 | 25 | private: 26 | HiButton * m_exitButton; 27 | bool m_Moveing; 28 | QPoint m_MovePosition; 29 | 30 | }; 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /hiButton.cpp: -------------------------------------------------------------------------------- 1 | #include "hiButton.h" 2 | 3 | HiButton::HiButton(QWidget *parent) 4 | : QPushButton(parent) 5 | { 6 | //设置图标无焦点 7 | setFocusPolicy(Qt::NoFocus); 8 | } 9 | 10 | HiButton::~HiButton() 11 | { 12 | } 13 | 14 | void HiButton::enterEvent(QEvent *) 15 | { 16 | if( isEnabled() && !focusIcon.isNull() ) 17 | setIcon(focusIcon); 18 | } 19 | 20 | void HiButton::leaveEvent(QEvent *) 21 | { 22 | if( isEnabled() ) 23 | setIcon(normalIcon); 24 | } 25 | 26 | 27 | void HiButton::mousePressEvent(QMouseEvent *event) 28 | { 29 | if( isEnabled() && !pressedIcon.isNull() ) 30 | setIcon(pressedIcon); 31 | QPushButton::mousePressEvent(event); 32 | } 33 | 34 | void HiButton::mouseReleaseEvent(QMouseEvent *event) 35 | { 36 | if( isEnabled() && !focusIcon.isNull() ) 37 | setIcon(focusIcon); 38 | QPushButton::mouseReleaseEvent(event); 39 | } 40 | 41 | void HiButton::hi_setButtonIcons(const QIcon &normal, const QIcon &focus, const QIcon &pressed) 42 | { 43 | normalIcon = normal; 44 | focusIcon = focus; 45 | pressedIcon = pressed; 46 | setIcon(normalIcon); 47 | } 48 | -------------------------------------------------------------------------------- /hiButton.h: -------------------------------------------------------------------------------- 1 | #ifndef HIBUTTON_H 2 | #define HIBUTTON_H 3 | 4 | //#include 5 | #include 6 | #include 7 | 8 | class HiButton : public QPushButton 9 | { 10 | Q_OBJECT 11 | public: 12 | HiButton(QWidget *parent = 0); 13 | ~HiButton(); 14 | 15 | //设置图标 16 | //若只指定一个图标,则默认“进入”,按下,松开都为此图标 17 | void hi_setButtonIcons(const QIcon &normal, const QIcon &focus = QIcon(), const QIcon &pressed = QIcon() ); 18 | 19 | protected: 20 | //重载“进入”和“离开”事件,进入时切换为另一个图标,离开时还原 21 | void enterEvent(QEvent *); 22 | void leaveEvent(QEvent *); 23 | 24 | //重载鼠标按下和松开事件 ,切换图标 25 | void mousePressEvent(QMouseEvent *event); 26 | void mouseReleaseEvent(QMouseEvent *event); 27 | private: 28 | QIcon normalIcon; 29 | QIcon focusIcon; 30 | QIcon pressedIcon; 31 | 32 | }; 33 | 34 | 35 | #endif//HIBUTTON_H 36 | -------------------------------------------------------------------------------- /hiLabel.cpp: -------------------------------------------------------------------------------- 1 | #include "hiLabel.h" 2 | #include 3 | 4 | HiLabel::HiLabel(QWidget *parent) 5 | :QLabel(parent) 6 | ,m_context("") 7 | ,m_timer(NULL) 8 | ,m_ms(0) 9 | ,m_pos(0) 10 | { 11 | } 12 | 13 | HiLabel::~HiLabel() 14 | { 15 | hi_stop(); 16 | } 17 | 18 | void HiLabel::hi_stop()//label停止滚动,直接从头显示文本 19 | { 20 | if (m_timer) 21 | { 22 | if (m_timer->isActive()) 23 | { 24 | m_timer->stop(); 25 | } 26 | delete m_timer; 27 | m_timer = NULL; 28 | } 29 | setText(m_context); 30 | } 31 | 32 | void HiLabel::hi_setText(const QString &context,const int &ms)//设置label文本和滚动的时间间隔 33 | { 34 | m_context = context; 35 | m_ms = ms; 36 | 37 | if (m_ms != 0 && m_timer == NULL) 38 | { 39 | m_timer = new QTimer(this); 40 | if (m_timer) 41 | { 42 | connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout())); 43 | m_timer->start(m_ms); 44 | } 45 | //return; 46 | } 47 | setText(m_context); 48 | } 49 | 50 | void HiLabel::slotTimeout()//定时器触发则显示滚动的文字 51 | { 52 | 53 | QString str=""; 54 | 55 | if (m_pos > m_context.count()) 56 | { 57 | m_pos = 0; 58 | } 59 | 60 | str = m_context.mid(m_pos); 61 | 62 | 63 | setText(str); 64 | //qDebug()<<"str:"< 4 | #include 5 | 6 | //实现带有文字滚动功能的Label 7 | class HiLabel : public QLabel 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit HiLabel(QWidget *parent=0); 12 | ~HiLabel(); 13 | 14 | //设置文本: 15 | //如果ms为0则文字不滚动(默认不滚动);若不为0则一定按时间间隔滚动; 16 | //如果调用setText()文字将不滚动(与使用QLabel相同); 17 | void hi_setText(const QString & context=0, const int & ms=0); 18 | 19 | //停止滚动 20 | void hi_stop(); 21 | 22 | private slots: 23 | 24 | void slotTimeout(); 25 | 26 | private: 27 | QString m_context; 28 | QTimer *m_timer; 29 | 30 | int m_ms; 31 | int m_pos; 32 | }; 33 | 34 | #endif//HILABEL_H 35 | -------------------------------------------------------------------------------- /hiLrcWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "hiLrcWidget.h" 2 | 3 | HiLrcWidget::HiLrcWidget(QWidget *parent) 4 | :QWidget(parent) 5 | { 6 | lrcLabel=nullptr; 7 | 8 | //无边界的窗口,总在最上 9 | setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); 10 | //去除窗体原背景(背景透明) 11 | setAttribute(Qt::WA_TranslucentBackground); 12 | 13 | //固定大小 14 | this->setFixedSize(800, 60); 15 | 16 | lrcLabel =new LrcLabel(this); 17 | lrcLabel->setGeometry(QRect(0, 6, 800, 60)); 18 | } 19 | 20 | HiLrcWidget::~HiLrcWidget() 21 | { 22 | if(lrcLabel!=nullptr) 23 | { 24 | delete lrcLabel; 25 | } 26 | } 27 | 28 | //开始歌词遮罩,以intervaltime(ms)为间隔时间 29 | void HiLrcWidget::hi_startLrcMask(qint64 intervaltime) 30 | { 31 | lrcLabel->hi_startLrcMask(intervaltime); 32 | } 33 | 34 | //停止歌词遮罩 35 | void HiLrcWidget::hi_stopLrcMask() 36 | { 37 | lrcLabel->hi_stopLrcMask(); 38 | } 39 | 40 | QString HiLrcWidget::text()const 41 | { 42 | return lrcLabel->text(); 43 | } 44 | 45 | void HiLrcWidget::hi_setLyricText(QString t)//设置歌词文本(无滚动效果) 46 | { 47 | lrcLabel->setText(t); 48 | } 49 | 50 | void HiLrcWidget::paintEvent(QPaintEvent * event) 51 | { 52 | QPainter p(this); 53 | p.drawPixmap(0, 0, QPixmap(":/hiplayer/resources/lrc_background.png")); 54 | lrcLabel->raise(); 55 | QWidget::paintEvent(event); 56 | } 57 | 58 | void HiLrcWidget::enterEvent(QEvent *) 59 | { 60 | setCursor(Qt::PointingHandCursor); 61 | } 62 | 63 | void HiLrcWidget::mousePressEvent(QMouseEvent *event) 64 | { 65 | m_Moveing=true; 66 | //记录下鼠标相对于窗口的位置 67 | //event->globalPos()鼠标按下时,鼠标相对于整个屏幕位置 68 | //pos() this->pos()鼠标按下时,窗口相对于父窗口的位置 69 | m_MovePosition=event->globalPos() - pos(); 70 | event->accept(); 71 | } 72 | 73 | void HiLrcWidget::mouseMoveEvent(QMouseEvent *event) 74 | { 75 | //(event->buttons() && Qt::LeftButton)按下是左键 76 | //鼠标移动事件需要移动窗口,窗口移动到哪里呢?就是要获取鼠标移动中,窗口在整个屏幕的坐标,然后move到这个坐标,怎么获取坐标? 77 | //通过事件event->globalPos()知道鼠标坐标,鼠标坐标减去鼠标相对于窗口位置,就是窗口在整个屏幕的坐标 78 | if (m_Moveing && (event->buttons() && Qt::LeftButton) 79 | && (event->globalPos()-m_MovePosition).manhattanLength() > QApplication::startDragDistance()) 80 | { 81 | move(event->globalPos()-m_MovePosition);//相对于桌面的位置. 82 | m_MovePosition = event->globalPos() - pos(); 83 | } 84 | event->accept(); 85 | } 86 | 87 | void HiLrcWidget::mouseReleaseEvent(QMouseEvent *) 88 | { 89 | m_Moveing=false; 90 | } 91 | -------------------------------------------------------------------------------- /hiLrcWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef HILRCWIDGET_H 2 | #define HILRCWIDGET_H 3 | #include 4 | #include "lrcLabel.h" 5 | #include 6 | 7 | class HiLrcWidget:public QWidget 8 | { 9 | public: 10 | HiLrcWidget(QWidget *parent = 0); 11 | ~HiLrcWidget(); 12 | 13 | //开始歌词遮罩,以intervaltime为间隔时间 14 | void hi_startLrcMask(qint64 intervaltime); 15 | 16 | //停止歌词遮罩 17 | void hi_stopLrcMask(); 18 | 19 | QString text()const; 20 | 21 | //void setText(QString t); 22 | 23 | void hi_setLyricText(QString t); 24 | private: 25 | void enterEvent(QEvent *); 26 | void paintEvent(QPaintEvent * event); 27 | //用于窗口位置拖动 28 | void mousePressEvent(QMouseEvent *event); 29 | void mouseMoveEvent(QMouseEvent *event); 30 | void mouseReleaseEvent(QMouseEvent *event); 31 | private: 32 | LrcLabel * lrcLabel; 33 | 34 | //用于窗口位置拖动 35 | bool m_Moveing; 36 | QPoint m_MovePosition; 37 | 38 | }; 39 | 40 | #endif // HILRCWIDGET_H 41 | -------------------------------------------------------------------------------- /hiVolBotton.cpp: -------------------------------------------------------------------------------- 1 | #include "hiVolBotton.h" 2 | #include 3 | 4 | HiVolBotton::HiVolBotton(QWidget *parent ) 5 | :QWidget(parent) 6 | { 7 | volSlider = new QSlider(Qt::Horizontal, this); 8 | volSlider->setRange(0, 100); 9 | volSlider->setGeometry(QRect(26,0,75,25)); 10 | 11 | //当音量条被拖动时发射音量改变的信号 12 | connect(volSlider, SIGNAL(valueChanged(int)), this, SIGNAL(hi_volumeChanged(int))); 13 | 14 | volSlider->setStyleSheet("QSlider::groove:horizontal{border:0px;height:4px;}" 15 | "QSlider::sub-page:horizontal{background:#0096ff;}" 16 | "QSlider::add-page:horizontal{background:lightgray;} " 17 | "QSlider::handle:horizontal{background:white;width:10px;border:#51b5fb 10px;border-radius:5px;margin:-3px 0px -3px 0px;}"); 18 | 19 | volBtn = new HiButton(this); 20 | 21 | QIcon icon_button, icon_button_focus; 22 | icon_button.addFile(QStringLiteral(":/hiplayer/resources/Volumn_40_40.png"), QSize(), QIcon::Normal, QIcon::Off); 23 | icon_button_focus.addFile(QStringLiteral(":/hiPlayer/resources/音量调节2.png"), QSize(), QIcon::Normal, QIcon::Off); 24 | volBtn->hi_setButtonIcons(icon_button, icon_button); 25 | 26 | volBtn->setIconSize(QSize(25,25)); 27 | volBtn->setFlat(true); 28 | volBtn->setFocusPolicy(Qt::NoFocus); 29 | volBtn->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 30 | volBtn->setGeometry(QRect(0,0,25,25)); 31 | 32 | connect(volBtn, SIGNAL(clicked()), this, SLOT(hi_buttonClicked())); 33 | 34 | menu = new QMenu(this); 35 | 36 | action = new QWidgetAction(this); 37 | action->setDefaultWidget(volSlider); 38 | menu->addAction(action); 39 | 40 | } 41 | void HiVolBotton::hi_setSliderVisiable(bool a) 42 | { 43 | volSlider->setVisible(a); 44 | } 45 | 46 | void HiVolBotton::hi_buttonClicked() 47 | { 48 | menu->exec(QCursor::pos()); 49 | } 50 | 51 | void HiVolBotton::hi_increaseVolume() 52 | { 53 | volSlider->triggerAction(QSlider::SliderPageStepAdd); 54 | qDebug()<<"hi_increaseVolume"; 55 | } 56 | 57 | void HiVolBotton::hi_descVolume() 58 | { 59 | volSlider->triggerAction(QSlider::SliderPageStepSub); 60 | qDebug()<<"hi_descVolume"; 61 | } 62 | 63 | int HiVolBotton::hi_getVolume() const 64 | { 65 | return volSlider->value(); 66 | } 67 | 68 | void HiVolBotton::hi_setVolume(int volume) 69 | { 70 | volSlider->setValue(volume); 71 | } 72 | -------------------------------------------------------------------------------- /hiVolBotton.h: -------------------------------------------------------------------------------- 1 | #ifndef HIVOLBOTTON_H 2 | #define HIVOLBOTTON_H 3 | 4 | #include "hiButton.h" 5 | #include 6 | 7 | class HiVolBotton:public QWidget 8 | { 9 | public: 10 | Q_OBJECT 11 | Q_PROPERTY(int hi_getVolume READ hi_getVolume WRITE hi_setVolume NOTIFY hi_volumeChanged) 12 | public: 13 | HiVolBotton(QWidget *parent = 0); 14 | 15 | //返回音量值(0~100) 16 | int hi_getVolume() const; 17 | 18 | //设置音量条是否可见 19 | void hi_setSliderVisiable(bool); 20 | 21 | public slots: 22 | 23 | //点击音量条使音量增加一部分 24 | void hi_increaseVolume(); 25 | 26 | //点击音量条使音量减少一部分 27 | void hi_descVolume(); 28 | 29 | //设置音量 30 | void hi_setVolume(int volume); 31 | 32 | //按钮单击事件,弹出菜单 33 | void hi_buttonClicked(); 34 | 35 | signals: 36 | 37 | //音量改变信号(当音量条被拖动时发射) 38 | void hi_volumeChanged(int volume); 39 | 40 | private: 41 | HiButton * volBtn; 42 | QSlider * volSlider; 43 | QMenu * menu; 44 | QWidgetAction * action; 45 | }; 46 | 47 | #endif // HIVOLBOTTON_H 48 | -------------------------------------------------------------------------------- /hiplayer.cpp: -------------------------------------------------------------------------------- 1 | #include "hiplayer.h" 2 | #include "miniWindow.h" 3 | 4 | HiPlayer::HiPlayer(QWidget *parent) 5 | : QWidget(parent) 6 | { 7 | hi_initUi(); 8 | hi_initPlayer(); 9 | hi_initConnections(); 10 | hi_initWindows(); 11 | hi_initMenuActions(); 12 | hi_initNetwork(); 13 | dirPath = QApplication::applicationDirPath(); 14 | slotReadList(); 15 | } 16 | 17 | HiPlayer::~HiPlayer() 18 | {} 19 | 20 | void HiPlayer::hi_initUi()//初始化界面 21 | { 22 | picLabel = new QLabel( this); 23 | picLabel->setGeometry(QRect(40, 45, 100, 100)); 24 | picLabel->setScaledContents(true); 25 | picLabel->setPixmap(QPixmap(":/hiplayer/resources/album.png")); 26 | 27 | nameLabel = new HiLabel(this); 28 | nameLabel->setGeometry(QRect(150, 55, 220, 20)); 29 | 30 | musicianLabel = new QLabel(this); 31 | musicianLabel->setGeometry(QRect(150, 85, 220, 15)); 32 | 33 | albumLabel = new QLabel(this); 34 | albumLabel->setGeometry(QRect(150, 115, 220, 15)); 35 | 36 | playSlider = new PlaySlider(this); 37 | playSlider->setObjectName(QStringLiteral("playSlider")); 38 | playSlider->setStyleSheet("QSlider::groove:horizontal{border:0px;height:4px;}" 39 | "QSlider::sub-page:horizontal{background:#0096ff;}" 40 | "QSlider::add-page:horizontal{background:lightgray;} " 41 | "QSlider::handle:horizontal{background:white;width:10px;border:#51b5fb 10px;border-radius:5px;margin:-3px 0px -3px 0px;}"); 42 | playSlider->setGeometry(QRect(40, 150, 290, 20)); 43 | playSlider->setOrientation(Qt::Horizontal); 44 | playSlider->setEnabled(false); 45 | 46 | timeLabel = new QLabel( this); 47 | timeLabel->setObjectName(QStringLiteral("timeLabel")); 48 | timeLabel->setGeometry(QRect(340, 150, 51, 16)); 49 | 50 | playlistTable = new QTableWidget( this); 51 | playlistTable->setObjectName(QStringLiteral("playlistTable")); 52 | playlistTable->setGeometry(QRect(25, 240, 350, 320)); 53 | playlistTable->setItemDelegate(new NoFocusDelegate()); 54 | 55 | addButton = new HiButton( this); 56 | addButton->setObjectName(QStringLiteral("addButton")); 57 | addButton->setGeometry(QRect(40, 190, 31, 31)); 58 | modeButton = new HiButton( this); 59 | modeButton->setObjectName(QStringLiteral("modeButton")); 60 | modeButton->setGeometry(QRect(290, 190, 31, 31)); 61 | lastButton = new HiButton( this); 62 | lastButton->setObjectName(QStringLiteral("lastButton")); 63 | lastButton->setGeometry(QRect(120, 185, 41, 41)); 64 | nextButton = new HiButton( this); 65 | nextButton->setObjectName(QStringLiteral("nextButton")); 66 | nextButton->setGeometry(QRect(240, 185, 41, 41)); 67 | lyricButton = new HiButton( this); 68 | lyricButton->setObjectName(QStringLiteral("lyricButton")); 69 | lyricButton->setGeometry(QRect(80, 190, 31, 31)); 70 | playButton = new HiButton( this); 71 | playButton->setObjectName(QStringLiteral("playButton")); 72 | playButton->setGeometry(QRect(170, 175, 61, 61)); 73 | pauseButton = new HiButton( this); 74 | pauseButton->setObjectName(QStringLiteral("pauseButton")); 75 | pauseButton->setGeometry(QRect(170, 175, 61, 61)); 76 | pauseButton->setVisible(false); 77 | 78 | volButton = new HiVolBotton(this); 79 | volButton->setObjectName(QStringLiteral("volButton")); 80 | volButton->setGeometry(QRect(333, 193, 31, 31)); 81 | volButton->hi_setVolume(50); 82 | 83 | minButton = new HiButton( this); 84 | minButton->setObjectName(QStringLiteral("minButton")); 85 | minButton->setGeometry(QRect(307, 3, 29, 31)); 86 | miniButton = new HiButton( this); 87 | miniButton->setObjectName(QStringLiteral("miniButton")); 88 | miniButton->setGeometry(QRect(337, 3, 29, 31)); 89 | exitButton = new HiButton( this); 90 | exitButton->setObjectName(QStringLiteral("exitButton")); 91 | exitButton->setGeometry(QRect(364, 3, 29, 31)); 92 | logoButton = new HiButton( this); 93 | logoButton->setObjectName(QStringLiteral("logoButton")); 94 | logoButton->setGeometry(QRect(8, 8, 38, 38)); 95 | 96 | logoButton->raise(); 97 | picLabel->raise(); 98 | playSlider->raise(); 99 | timeLabel->raise(); 100 | playlistTable->raise(); 101 | addButton->raise(); 102 | modeButton->raise(); 103 | nextButton->raise(); 104 | lyricButton->raise(); 105 | playButton->raise(); 106 | volButton->raise(); 107 | minButton->raise(); 108 | miniButton->raise(); 109 | exitButton->raise(); 110 | 111 | timeLabel->setText(tr("00:00")); 112 | nameLabel->setText(tr("Name " )); 113 | musicianLabel->setText(tr("Musician" )); 114 | albumLabel->setText(tr("Album" )); 115 | 116 | //设置图标 117 | QIcon icon_play, icon_play_focus; 118 | icon_play.addFile(QStringLiteral(":/hiplayer/resources/Play_100_100.png"), QSize(), QIcon::Normal, QIcon::Off); 119 | icon_play_focus.addFile(QStringLiteral(":/hiPlayer/resources/播放按钮-主界面2.png"), QSize(), QIcon::Normal, QIcon::Off); 120 | playButton->hi_setButtonIcons(icon_play, icon_play); 121 | playButton->setIconSize(QSize(60,60)); 122 | playButton->setFlat(true); 123 | playButton->setFocusPolicy(Qt::NoFocus); 124 | playButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 125 | 126 | QIcon icon_pause, icon_pause_focus; 127 | icon_pause.addFile(QStringLiteral(":/hiplayer/resources/Pause_100_100.png"), QSize(), QIcon::Normal, QIcon::Off); 128 | icon_pause_focus.addFile(QStringLiteral(":/hiPlayer/resources/暂停按钮-主界面2.png"), QSize(), QIcon::Normal, QIcon::Off); 129 | pauseButton->hi_setButtonIcons(icon_pause, icon_pause); 130 | pauseButton->setIconSize(QSize(60,60)); 131 | pauseButton->setFlat(true); 132 | pauseButton->setFocusPolicy(Qt::NoFocus); 133 | pauseButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 134 | 135 | 136 | QIcon icon_lyric, icon_lyric_focus; 137 | icon_lyric.addFile(QStringLiteral(":/hiplayer/resources/Lyric_40_40.png"), QSize(), QIcon::Normal, QIcon::Off); 138 | icon_lyric_focus.addFile(QStringLiteral(":/hiPlayer/resources/歌词按钮2.png"), QSize(), QIcon::Normal, QIcon::Off); 139 | lyricButton->hi_setButtonIcons(icon_lyric, icon_lyric); 140 | lyricButton->setIconSize(QSize(25,25)); 141 | lyricButton->setFlat(true); 142 | lyricButton->setFocusPolicy(Qt::NoFocus); 143 | lyricButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 144 | 145 | QIcon icon_exit, icon_exit_focus; 146 | icon_exit.addFile(QStringLiteral(":/hiplayer/resources/关闭.png"), QSize(), QIcon::Normal, QIcon::Off); 147 | icon_exit_focus.addFile(QStringLiteral(":/hiPlayer/resources/关闭按钮2.png"), QSize(), QIcon::Normal, QIcon::Off); 148 | exitButton->hi_setButtonIcons(icon_exit, icon_exit); 149 | exitButton->setIconSize(QSize(18,18)); 150 | exitButton->setFlat(true); 151 | exitButton->setFocusPolicy(Qt::NoFocus); 152 | exitButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 153 | 154 | QIcon icon_min, icon_min_focus; 155 | icon_min.addFile(QStringLiteral(":/hiplayer/resources/缩小.png"), QSize(), QIcon::Normal, QIcon::Off); 156 | icon_min_focus.addFile(QStringLiteral(":/hiPlayer/resources/迷你模式按钮2.png"), QSize(), QIcon::Normal, QIcon::Off); 157 | miniButton->hi_setButtonIcons(icon_min, icon_min); 158 | miniButton->setIconSize(QSize(18,18)); 159 | miniButton->setFlat(true); 160 | miniButton->setFocusPolicy(Qt::NoFocus); 161 | miniButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 162 | 163 | QIcon icon_mmin, icon_mmin_focus; 164 | icon_mmin.addFile(QStringLiteral(":/hiplayer/resources/最小化.png"), QSize(), QIcon::Normal, QIcon::Off); 165 | icon_mmin_focus.addFile(QStringLiteral(":/hiPlayer/resources/缩小按钮2.png"), QSize(), QIcon::Normal, QIcon::Off); 166 | minButton->hi_setButtonIcons(icon_mmin, icon_mmin); 167 | minButton->setIconSize(QSize(18,18)); 168 | minButton->setFlat(true); 169 | minButton->setFocusPolicy(Qt::NoFocus); 170 | minButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 171 | 172 | QIcon icon_logo, icon_logo_focus; 173 | icon_logo.addFile(QStringLiteral(":/hiplayer/resources/HiPlayer_38_38.png"), QSize(), QIcon::Normal, QIcon::Off); 174 | icon_logo_focus.addFile(QStringLiteral(":/hiPlayer/resources/左上角logo按钮2.png"), QSize(), QIcon::Normal, QIcon::Off); 175 | logoButton->hi_setButtonIcons(icon_logo, icon_logo); 176 | logoButton->setIconSize(QSize(48, 48)); 177 | logoButton->setFlat(true); 178 | logoButton->setFocusPolicy(Qt::NoFocus); 179 | logoButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 180 | 181 | QIcon icon_next, icon_next_focus; 182 | icon_next.addFile(QStringLiteral(":/hiplayer/resources/Next_40_40.png"), QSize(), QIcon::Normal, QIcon::Off); 183 | icon_next_focus.addFile(QStringLiteral(":/hiPlayer/resources/下一曲2.png"), QSize(), QIcon::Normal, QIcon::Off); 184 | nextButton->hi_setButtonIcons(icon_next, icon_next); 185 | nextButton->setIconSize(QSize(40,40)); 186 | nextButton->setFlat(true); 187 | nextButton->setFocusPolicy(Qt::NoFocus); 188 | nextButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 189 | 190 | QIcon icon_last, icon_last_focus; 191 | icon_last.addFile(QStringLiteral(":/hiplayer/resources/Last_40_40.png"), QSize(), QIcon::Normal, QIcon::Off); 192 | icon_last_focus.addFile(QStringLiteral(":/hiPlayer/resources/上一曲2.png"), QSize(), QIcon::Normal, QIcon::Off); 193 | lastButton->hi_setButtonIcons(icon_last, icon_last); 194 | lastButton->setIconSize(QSize(40,40)); 195 | lastButton->setFlat(true); 196 | lastButton->setFocusPolicy(Qt::NoFocus); 197 | lastButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 198 | 199 | QIcon icon_mode, icon_mode_focus; 200 | icon_mode.addFile(QStringLiteral(":/hiplayer/resources/mode.png"), QSize(), QIcon::Normal, QIcon::Off); 201 | icon_mode_focus.addFile(QStringLiteral(":/hiPlayer/resources/播放模式2.png"), QSize(), QIcon::Normal, QIcon::Off); 202 | modeButton->hi_setButtonIcons(icon_mode, icon_mode); 203 | modeButton->setIconSize(QSize(25,25)); 204 | modeButton->setFlat(true); 205 | modeButton->setFocusPolicy(Qt::NoFocus); 206 | modeButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 207 | 208 | QIcon icon_add, icon_add_focus; 209 | icon_add.addFile(QStringLiteral(":/hiplayer/resources/addMusic_40_40.png"), QSize(), QIcon::Normal, QIcon::Off); 210 | icon_add_focus.addFile(QStringLiteral(":/hiPlayer/resources/添加歌曲2.png"), QSize(), QIcon::Normal, QIcon::Off); 211 | addButton->hi_setButtonIcons(icon_add, icon_add); 212 | addButton->setIconSize(QSize(25,25)); 213 | addButton->setFlat(true); 214 | addButton->setFocusPolicy(Qt::NoFocus); 215 | addButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 216 | 217 | //去除标题栏 218 | this->setWindowFlags(Qt::FramelessWindowHint); 219 | //半透明 220 | this->setWindowOpacity(1); 221 | setAttribute(Qt::WA_TranslucentBackground); 222 | 223 | //固定大小 224 | this->setFixedSize(400, 600); 225 | 226 | //设置音乐信息字体颜色 227 | QColor fontcolor(1, 149, 255); 228 | QPalette fontPalette; 229 | fontPalette.setColor(QPalette::WindowText, fontcolor); 230 | nameLabel->setPalette(fontPalette); 231 | musicianLabel->setPalette(fontPalette); 232 | albumLabel->setPalette(fontPalette); 233 | 234 | QColor timeColor(106, 182, 240); 235 | QPalette timePalette; 236 | timePalette.setColor(QPalette::WindowText, timeColor); 237 | timeLabel->setPalette(timePalette); 238 | 239 | nameLabel->setFont(QFont(QString::fromUtf8("微软雅黑"), 12)); 240 | 241 | QFont othersfont(QString::fromUtf8("微软雅黑"), 9); 242 | musicianLabel->setFont(othersfont); 243 | albumLabel->setFont(othersfont); 244 | timeLabel->setFont(othersfont); 245 | 246 | if (playlistTable->columnCount() < 1)//列数默认为0 247 | playlistTable->setColumnCount(2); 248 | 249 | //设置列宽 250 | playlistTable->setColumnWidth(0,300); 251 | playlistTable->setColumnWidth(1,45); 252 | //禁止编辑单元格内容 253 | playlistTable->setEditTriggers(QAbstractItemView::NoEditTriggers); 254 | //选中一行 255 | playlistTable->setSelectionBehavior(QAbstractItemView::SelectRows); 256 | //去掉水平滚动条 257 | playlistTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 258 | //垂直滚动条按项移动 259 | playlistTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); 260 | //去除水平表头 261 | playlistTable->horizontalHeader()->setFixedHeight(0); 262 | //去除垂直表头 263 | playlistTable->verticalHeader()->setFixedWidth(0); 264 | //设置无边框 265 | playlistTable->setFrameShape(QFrame::NoFrame); 266 | //设置不显示格子线 267 | playlistTable->setShowGrid(false); 268 | //设置右键菜单 269 | playlistTable->setContextMenuPolicy(Qt::CustomContextMenu); 270 | //设置背景颜色 271 | QPalette pal; 272 | pal.setBrush(QPalette::Base, QBrush(QColor(255, 255, 255))); 273 | playlistTable->setPalette(pal); 274 | //设置竖直滚动条样式 275 | playlistTable->setStyleSheet("QScrollBar{background:transparent; width: 5px;}" 276 | "QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}" 277 | "QScrollBar::handle:hover{background:gray;}" 278 | "QScrollBar::sub-line{background:transparent;}" 279 | "QScrollBar::add-line{background:transparent;}"); 280 | //使拖动操作生效 281 | playlistTable->setAcceptDrops(true); 282 | setAcceptDrops(true); 283 | } 284 | 285 | void HiPlayer::hi_initPlayer()//初始化播放器,设置播放模式为单曲播放 286 | { 287 | mediaPlayer = new QMediaPlayer(this); 288 | mediaList = new QMediaPlaylist(this); 289 | mediaPlayer->setPlaylist(mediaList); 290 | 291 | playMode = Play_Mode::SINGAL; 292 | //preIndex = -1; 293 | currentIndex = 0; 294 | 295 | mediaList->setPlaybackMode(QMediaPlaylist::CurrentItemOnce); 296 | } 297 | 298 | void HiPlayer::hi_initConnections() 299 | { 300 | connect(mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(slotUpdatePosition(qint64))); 301 | connect(mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(slotUpdateProcessbar(qint64))); 302 | connect(mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)),this, SLOT(slotUpdateState(QMediaPlayer::State))); 303 | connect(mediaPlayer, SIGNAL(metaDataChanged()), this, SLOT(slotUpdateMetaData())); 304 | connect(playSlider, SIGNAL(sliderMoved(int)), this, SLOT(slotSetPlayPosition(int))); 305 | connect(playSlider, SIGNAL(sliderReleased()), this, SLOT(slotSetPosition())); 306 | //connect(playSlider,SIGNAL(valueChanged(int)),this,SLOT(slotPlayValueChanged(int))); 307 | connect(volButton, SIGNAL(hi_volumeChanged(int)), mediaPlayer, SLOT(setVolume(int))); 308 | 309 | connect(playlistTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(slotPlaylistDoubleClicked(int, int))); 310 | connect(playlistTable, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotPlaylistMenuRequested(const QPoint &))); 311 | 312 | connect(addButton, SIGNAL(clicked()), this, SLOT(slotOpenMusic())); 313 | connect(exitButton, SIGNAL(clicked()), this, SLOT(close())); 314 | connect(playButton, SIGNAL(clicked()), this, SLOT(slotPlayButtonClicked())); 315 | connect(lyricButton, SIGNAL(clicked()), this, SLOT(slotLyricButtonClicked())); 316 | connect(logoButton, SIGNAL(clicked()), this, SLOT(slotLogoButtonClicked())); 317 | connect(modeButton, SIGNAL(clicked()), this, SLOT(slotModeButtonClicked())); 318 | connect(nextButton, SIGNAL(clicked()), this, SLOT(slotNextButtonClicked())); 319 | connect(lastButton, SIGNAL(clicked()), this, SLOT(slotLastButtonClicked())); 320 | connect(pauseButton, SIGNAL(clicked()), this, SLOT(slotPauseButtonClicked())); 321 | connect(miniButton, SIGNAL(clicked()), this, SLOT(slotMinButtonClicked())); 322 | connect(minButton, SIGNAL(clicked()), this, SLOT(showMinimized())); 323 | 324 | connect(playSlider,SIGNAL(sigValueClicked(int)),this,SLOT(slotSliderValueClicked(int))); 325 | } 326 | 327 | 328 | void HiPlayer::hi_initWindows() 329 | { 330 | aboutForm = new AboutDialog(); 331 | aboutForm->hide(); 332 | lrcWidget = new HiLrcWidget(this); 333 | 334 | miniForm = new MiniWindow(this); 335 | miniForm->hide(); 336 | } 337 | 338 | void HiPlayer::hi_initMenuActions() 339 | { 340 | modeSingal = new QAction(QString::fromUtf8("单曲播放"), this); 341 | modeListCircle = new QAction(QString::fromUtf8("列表循环"), this); 342 | modeSingalCircle = new QAction(QString::fromUtf8("单曲循环"), this); 343 | modeRandom = new QAction(QString::fromUtf8("随机播放"), this); 344 | 345 | connect(modeSingal, SIGNAL(triggered()), this, SLOT(slotSetPlayMode())); 346 | connect(modeListCircle, SIGNAL(triggered()), this, SLOT(slotSetPlayMode())); 347 | connect(modeSingalCircle, SIGNAL(triggered()), this, SLOT(slotSetPlayMode())); 348 | connect(modeRandom, SIGNAL(triggered()), this, SLOT(slotSetPlayMode())); 349 | 350 | modeActionGroup = new QActionGroup(this); 351 | modeActionGroup->addAction(modeSingal); 352 | modeActionGroup->addAction(modeListCircle); 353 | modeActionGroup->addAction(modeSingalCircle); 354 | modeActionGroup->addAction(modeRandom); 355 | 356 | 357 | modeSingal->setCheckable(true); 358 | modeListCircle->setCheckable(true); 359 | modeSingalCircle->setCheckable(true); 360 | modeRandom->setCheckable(true); 361 | modeSingal->setChecked(true); 362 | 363 | playModeMenu = new QMenu(modeButton); 364 | playModeMenu->setStyleSheet( 365 | "QMenu{padding:5px;background:white;border:1px solid gray;}" 366 | "QMenu::item{padding:0px 40px 0px 30px;height:25px;}" 367 | "QMenu::item:selected:enabled{background:#0096ff;color:white;}" 368 | "QMenu::item:selected:!enabled{background:transparent;}" 369 | "QMenu::separator{height:1px;background:lightgray;margin:5px 0px 5px 0px;}"); 370 | playModeMenu->addActions(modeActionGroup->actions()); 371 | 372 | 373 | contextMenuLess = new QMenu(playlistTable); 374 | contextMenuMore = new QMenu(playlistTable); 375 | addMusic = new QAction(QString::fromUtf8("添加歌曲"),this); 376 | addFileDiv = new QAction(QString::fromUtf8("添加目录"),this); 377 | removeCurr = new QAction(QString::fromUtf8("移除本曲"),this); 378 | removeAll = new QAction(QString::fromUtf8("移除所有"),this); 379 | 380 | connect(addMusic, SIGNAL(triggered()), this, SLOT(slotOpenMusic())); 381 | connect(addFileDiv, SIGNAL(triggered()), this, SLOT(slotOpenDir())); 382 | connect(removeCurr, SIGNAL(triggered()), this, SLOT(slotRemoveCurrentMusic())); 383 | connect(removeAll, SIGNAL(triggered()), this, SLOT(slotClearList())); 384 | 385 | contextMenuLess->addAction(addMusic); 386 | contextMenuLess->addAction(addFileDiv); 387 | contextMenuLess->addSeparator(); 388 | contextMenuLess->addAction(removeAll); 389 | 390 | contextMenuMore->addAction(addMusic); 391 | contextMenuMore->addAction(addFileDiv); 392 | contextMenuMore->addSeparator(); 393 | contextMenuMore->addAction(removeCurr); 394 | contextMenuMore->addAction(removeAll); 395 | 396 | contextMenuLess->setStyleSheet( 397 | "QMenu{padding:5px;background:white;border:1px solid gray;}" 398 | "QMenu::item{padding:0px 40px 0px 30px;height:25px;}" 399 | "QMenu::item:selected:enabled{background:#0096ff;color:white;}" 400 | "QMenu::item:selected:!enabled{background:transparent;}" 401 | "QMenu::separator{height:1px;background:lightgray;margin:5px 0px 5px 0px;}"); 402 | 403 | contextMenuMore->setStyleSheet( 404 | "QMenu{padding:5px;background:white;border:1px solid gray;}" 405 | "QMenu::item{padding:0px 40px 0px 30px;height:25px;}" 406 | "QMenu::item:selected:enabled{background:#0096ff;color:white;}" 407 | "QMenu::item:selected:!enabled{background:transparent;}" 408 | "QMenu::separator{height:1px;background:lightgray;margin:5px 0px 5px 0px;}"); 409 | 410 | } 411 | 412 | void HiPlayer::dropEvent(QDropEvent *event) 413 | { 414 | QList urls = event->mimeData()->urls(); 415 | if(urls.isEmpty()) 416 | return; 417 | 418 | QStringList dropfilename; 419 | foreach(QUrl u, urls){ 420 | if (u.toString().right(4) == QString(".mp3")){ 421 | dropfilename.append(u.toLocalFile()); 422 | } 423 | } 424 | 425 | if(!dropfilename.isEmpty()){ 426 | hi_addList(dropfilename); 427 | } 428 | qDebug()<<"HiPlayer::dropEvent"; 429 | } 430 | 431 | void HiPlayer::dragEnterEvent(QDragEnterEvent *event) 432 | { 433 | if(event->mimeData()->hasFormat("text/uri-list")) 434 | event->acceptProposedAction(); 435 | } 436 | 437 | void HiPlayer::paintEvent(QPaintEvent * event) 438 | { 439 | QPainter p(this); 440 | p.drawPixmap(0, 0 , QPixmap(":/hiplayer/resources/background.png")); 441 | logoButton->raise(); 442 | picLabel->raise(); 443 | playSlider->raise(); 444 | timeLabel->raise(); 445 | playlistTable->raise(); 446 | addButton->raise(); 447 | modeButton->raise(); 448 | nextButton->raise(); 449 | lyricButton->raise(); 450 | playButton->raise(); 451 | volButton->raise(); 452 | minButton->raise(); 453 | miniButton->raise(); 454 | exitButton->raise(); 455 | QWidget::paintEvent(event); 456 | } 457 | 458 | void HiPlayer::slotPlaylistDoubleClicked(int row, int )//双击本地歌单列表 459 | { 460 | QFile file(playList.at(row)); 461 | if (!file.open(QIODevice::ReadOnly)) 462 | { 463 | playlistTable->item(row,1)->setText(QString::fromUtf8("失效")); 464 | return; 465 | } 466 | file.close(); 467 | mediaList->setCurrentIndex(row); 468 | mediaPlayer->play(); 469 | playlistTable->item(row, 1)->setText(QString::fromUtf8("")); 470 | } 471 | 472 | void HiPlayer::slotRemoveCurrentMusic()//清除当前列表中的音乐后更新本地用于记录列表的数据文件 473 | { 474 | playList.removeAt(currentIndex); 475 | playlistTable->removeRow(currentIndex); 476 | mediaList->removeMedia(currentIndex); 477 | hi_setTableColor(); 478 | slotWriteList(); 479 | } 480 | 481 | void HiPlayer::slotOpenMusic()//打开音乐菜单 482 | { 483 | QStringList fileList = QFileDialog::getOpenFileNames(this,QString::fromUtf8("添加音乐"),QString(),QString("MP3 (*.mp3)")); 484 | hi_addList(fileList); 485 | } 486 | 487 | void HiPlayer::slotOpenDir()//打开目录菜单 488 | { 489 | QString dirPath = QFileDialog::getExistingDirectory(this,QString::fromUtf8("选择目录")); 490 | if(dirPath.size() == 0) 491 | return; 492 | //if(QFileDialog::Reject) return; 493 | QDir dir(dirPath); 494 | QStringList fileList = dir.entryList(QStringList()<<"*.mp3",QDir::Files); 495 | for(int i = 0;i < fileList.size();i ++) 496 | fileList[i] = dir.absoluteFilePath(fileList.at(i)); 497 | hi_addList(fileList); 498 | } 499 | 500 | void HiPlayer::slotClearList()//清除歌曲列表 501 | { 502 | mediaPlayer->stop(); 503 | playList.clear(); 504 | mediaList->clear(); 505 | while(playlistTable->rowCount()) 506 | playlistTable->removeRow(0); 507 | 508 | //清除记录歌曲列表的文件 509 | QFile file(dirPath + "/HiPlayerList.list"); 510 | if (file.exists()) 511 | { 512 | file.remove(); 513 | } 514 | 515 | timeLabel->setText(tr("00:00")); 516 | nameLabel->setText(tr("Name " )); 517 | nameLabel->hi_stop(); 518 | musicianLabel->setText(tr("Musician" )); 519 | albumLabel->setText(tr("Album" )); 520 | } 521 | 522 | void HiPlayer::hi_addList(QStringList list)//将文件列表list添加到界面列表上,并更新数据文件 523 | { 524 | foreach(QString fileName,list) 525 | { 526 | if(playList.contains(fileName))//默认大小写敏感 527 | continue; 528 | playList.append(fileName); 529 | 530 | mediaList->addMedia(QUrl::fromLocalFile(fileName)); 531 | playlistTable->insertRow(playlistTable->rowCount());//playlistTable行号包括0 532 | 533 | for(int i = 0;i < playlistTable->columnCount();i++){ 534 | QTableWidgetItem *item = new QTableWidgetItem; 535 | item->setFont(QFont(QString::fromUtf8("微软雅黑"), 10)); 536 | 537 | playlistTable->setItem(playlistTable->rowCount() - 1,i,item); 538 | } 539 | playlistTable->item(playlistTable->rowCount() - 1,0)->setText(QFileInfo(fileName).baseName()); 540 | } 541 | hi_setTableColor(); 542 | slotWriteList(); 543 | } 544 | 545 | void HiPlayer::slotPlaylistMenuRequested(const QPoint &pos)//请求右键菜单 546 | { 547 | if(playlistTable->itemAt(pos)) 548 | { 549 | currentIndex = playlistTable->rowAt(pos.y()); 550 | contextMenuMore->exec(QCursor::pos()); 551 | } 552 | else contextMenuLess->exec(QCursor::pos()); 553 | } 554 | 555 | void HiPlayer::slotSetPosition()//更新播放进度 556 | { 557 | int pos = slotGetPlayPosition(); 558 | mediaPlayer->setPosition(pos); 559 | mediaPlayer->play(); 560 | playButton->setVisible(false); 561 | pauseButton->setVisible(true); 562 | 563 | } 564 | 565 | void HiPlayer::slotUpdatePosition(qint64 position)//更新歌词、时间显示 566 | { 567 | if (!playSlider->isSliderDown()){//判断slider未被按下. 568 | playSlider->setValue(position); 569 | } 570 | 571 | //获取该音频文件的总时长参数,单位为毫秒 572 | qint64 total_time_value = mediaPlayer->duration(); 573 | 574 | //传进来的time参数代表了当前的时间 575 | //这3个参数分别代表了时,分,秒;60000毫秒为1分钟,所以分钟第二个参数是先除6000,第3个参数是直接除1s 576 | QTime current_time(0, (position/60000)%60, (position/1000)%60); 577 | timeLabel->setText(current_time.toString(tr("mm:ss"))); 578 | 579 | // 获取当期时间对应的歌词 580 | if(!lrcMap.isEmpty()) //QMap lrcMap; 581 | { 582 | // 获取当前时间在歌词中的前后两个时间点 583 | qint64 previous = 0; 584 | qint64 later = 0; 585 | 586 | //keys()方法返回lrcMap的keys列表 587 | foreach (qint64 value1, lrcMap.keys()) {//QMap lrcMap; 588 | if (position >= value1) { 589 | previous = value1; 590 | } else { 591 | later = value1; 592 | break;//获取该位置所在的歌词的前后时间点. 593 | } 594 | } 595 | 596 | // 到达最后一行,将later设置为歌曲总时间的值 597 | if (later == 0) 598 | later = total_time_value; 599 | 600 | // 获取当前时间所对应的歌词内容 601 | QString current_lrc = lrcMap.value(previous); 602 | 603 | // 如果是新的一行歌词,那么重新开始显示歌词遮罩 604 | QString tmp = lrcWidget->text(); 605 | if(current_lrc != tmp) 606 | { 607 | lrcWidget->hi_setLyricText(current_lrc); 608 | tmp = lrcWidget->text(); 609 | qint64 interval_time = later - previous; 610 | lrcWidget->hi_startLrcMask(interval_time); 611 | } 612 | } 613 | } 614 | 615 | void HiPlayer::slotUpdateProcessbar(qint64 duration)//更新进度条长度等信息 616 | { 617 | playSlider->setRange(0, duration); 618 | playSlider->setEnabled(duration > 0); 619 | playSlider->setPageStep(duration / 10); 620 | } 621 | 622 | void HiPlayer::slotUpdateMetaData()//更新显示在界面上的正在播放音乐的信息 623 | { 624 | currentIndex = mediaList->currentIndex();//正常情况下,返回值从0开始 625 | songName.clear(); 626 | songArtist.clear(); 627 | lrcMap.clear(); 628 | picLabel->setPixmap(QPixmap(":/hiplayer/resources/album.png")); 629 | 630 | if(currentIndex<0)//单曲播放模式下,歌曲播放结束之后mediaList->currentIndex()返回-1 631 | { 632 | 633 | timeLabel->setText(tr("00:00")); 634 | nameLabel->setText(tr("Name " )); 635 | nameLabel->hi_stop(); 636 | musicianLabel->setText(tr("Musician" )); 637 | albumLabel->setText(tr("Album" )); 638 | return; 639 | } 640 | playingFile = playList.at(currentIndex); 641 | songName = mediaPlayer->metaData(QMediaMetaData::Title).toString();//通过歌曲文件获取歌名 642 | if (songName.size() > 28) 643 | nameLabel->hi_setText(songName, TEXT_SPEED);//label中的文字滚动出现 644 | else{ 645 | nameLabel->hi_stop(); 646 | nameLabel->setText(songName); 647 | } 648 | 649 | songArtist = mediaPlayer->metaData(QMediaMetaData::Author).toString(); 650 | musicianLabel->setText(songArtist); 651 | albumLabel->setText(mediaPlayer->metaData(QMediaMetaData::AlbumTitle).toString()); 652 | 653 | lrcWidget->hi_setLyricText(songName); 654 | 655 | if (!songName.isEmpty()) 656 | {//若歌曲名不为空,则搜索图片和歌词 657 | bool pic = hi_getPicFromFile(); 658 | bool lrc = slotResolveLrc(playingFile); 659 | if (!(pic && lrc)) 660 | {//本地均没有找到专辑图片和歌词 661 | receiveState = RECEIVE_INFO; 662 | hi_fetchNetData();//获取网络数据 663 | } 664 | } 665 | 666 | if(nameLabel->text() == "") 667 | nameLabel->setText(QString::fromUtf8("未知歌曲")); 668 | if(musicianLabel->text() == "") 669 | musicianLabel->setText(QString::fromUtf8("未知音乐家")); 670 | if(albumLabel->text() == "") 671 | albumLabel->setText(QString::fromUtf8("未知专辑")); 672 | } 673 | 674 | void HiPlayer::slotUpdateState(QMediaPlayer::State state)//更新播放状态 675 | { 676 | if (state == QMediaPlayer::PlayingState) { 677 | playSlider->setEnabled(true); 678 | playButton->setVisible(false); 679 | pauseButton->setVisible(true); 680 | } else { 681 | playButton->setVisible(true); 682 | pauseButton->setVisible(false); 683 | } 684 | if (state != QMediaPlayer::StoppedState){ 685 | playingFile = playList.at(mediaList->currentIndex()); 686 | slotResolveLrc(playingFile); 687 | } 688 | else 689 | { 690 | playSlider->setEnabled(false); 691 | } 692 | } 693 | 694 | void HiPlayer::slotSliderValueClicked(int value)//单击播放进度条触发 695 | { 696 | slotSetPlayPosition(value); 697 | slotSetPosition(); 698 | } 699 | 700 | void HiPlayer::slotPlayButtonClicked()//单击播放按键触发 701 | { 702 | if(mediaPlayer->state() == QMediaPlayer::PausedState) 703 | { 704 | mediaPlayer->play(); 705 | } 706 | } 707 | 708 | void HiPlayer::slotPauseButtonClicked()//单击暂停按键触发 709 | { 710 | 711 | if(mediaPlayer->state() == QMediaPlayer::PlayingState){ 712 | mediaPlayer->pause(); 713 | } 714 | } 715 | 716 | void HiPlayer::slotNextButtonClicked()//点击播放下一首按钮触发 717 | { 718 | mediaList->setPlaybackMode(QMediaPlaylist::Loop); 719 | 720 | mediaList->setCurrentIndex(mediaList->nextIndex()); 721 | if (!mediaPlayer->isAudioAvailable()){ 722 | playlistTable->item(mediaList->currentIndex(), 1)->setText(QString::fromUtf8("失效")); 723 | } 724 | mediaPlayer->play(); 725 | playlistTable->item(mediaList->currentIndex(), 1)->setText(QString::fromUtf8("")); 726 | slotSetPlayMode();//恢复原有的播放模式 727 | } 728 | 729 | void HiPlayer::slotLastButtonClicked()//单击播放上一首按钮触发 730 | { 731 | mediaList->setPlaybackMode(QMediaPlaylist::Loop); 732 | 733 | mediaList->setCurrentIndex(mediaList->previousIndex()); 734 | if (!mediaPlayer->isAudioAvailable()){ 735 | playlistTable->item(mediaList->currentIndex(), 1)->setText(QString::fromUtf8("失效")); 736 | } 737 | 738 | mediaPlayer->play(); 739 | playlistTable->item(mediaList->currentIndex(), 1)->setText(QString::fromUtf8("")); 740 | slotSetPlayMode();//恢复原有的播放模式 741 | } 742 | 743 | void HiPlayer::slotLyricButtonClicked()//单击歌词按键触发 744 | { 745 | if(lrcWidget->isHidden()) 746 | { 747 | lrcWidget->show(); 748 | QDesktopWidget* desktopWidget = QApplication::desktop(); 749 | 750 | //获取设备屏幕大小 751 | QRect screenRect = desktopWidget->screenGeometry(); 752 | 753 | int height=screenRect.height(); 754 | int width=screenRect.width(); 755 | 756 | int formheight=lrcWidget->height(); 757 | int formwidth=lrcWidget->width(); 758 | int newformx=width/2-formwidth/2; 759 | int newformy=height-formheight*2; 760 | lrcWidget->move(newformx,newformy); 761 | 762 | } 763 | 764 | else lrcWidget->hide(); 765 | } 766 | 767 | void HiPlayer::slotLogoButtonClicked()//单击左上角logo触发 768 | { 769 | aboutForm->show(); 770 | } 771 | 772 | void HiPlayer::slotModeButtonClicked()//单击播放模式按键触发 773 | { 774 | playModeMenu->exec(QCursor::pos()); 775 | } 776 | 777 | void HiPlayer::slotMinButtonClicked()//单击缩小按键触发 778 | { 779 | miniForm->show(); 780 | miniForm->hi_initPlayMode(volButton->hi_getVolume()); 781 | this->hide(); 782 | } 783 | 784 | void HiPlayer::slotSetPlayMode()//设置播放模式 785 | { 786 | if(modeSingal->isChecked()) { 787 | playMode = Play_Mode::SINGAL; 788 | mediaList->setPlaybackMode(QMediaPlaylist::CurrentItemOnce); 789 | } 790 | else if(modeListCircle->isChecked()) { 791 | playMode = Play_Mode::LISTCIRCLE; 792 | mediaList->setPlaybackMode(QMediaPlaylist::Loop); 793 | } 794 | else if(modeSingalCircle->isChecked()) { 795 | playMode = Play_Mode::SINGALCIRCLE; 796 | mediaList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop); 797 | } 798 | else if(modeRandom->isChecked()) { 799 | playMode = Play_Mode::RANDOM; 800 | mediaList->setPlaybackMode(QMediaPlaylist::Random); 801 | } 802 | } 803 | 804 | void HiPlayer::slotSetModeFromMini(int m)//从Mini窗口获取播放模式 805 | { 806 | switch(m){ 807 | case 0: 808 | playMode = Play_Mode::SINGAL; 809 | mediaList->setPlaybackMode(QMediaPlaylist::CurrentItemOnce); 810 | modeSingal->setChecked(true); 811 | break; 812 | case 1: 813 | playMode = Play_Mode::LISTCIRCLE; 814 | mediaList->setPlaybackMode(QMediaPlaylist::Loop); 815 | modeListCircle->setChecked(true); 816 | break; 817 | case 2: 818 | playMode = Play_Mode::SINGALCIRCLE; 819 | mediaList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop); 820 | modeSingalCircle->setChecked(true); 821 | break; 822 | case 3: 823 | playMode = Play_Mode::RANDOM; 824 | mediaList->setPlaybackMode(QMediaPlaylist::Random); 825 | modeRandom->setChecked(true); 826 | break; 827 | 828 | } 829 | } 830 | 831 | 832 | void HiPlayer::slotSetVolFromMini(int a)//从Mini窗口获取音量 833 | { 834 | volButton->hi_setVolume(a); 835 | } 836 | 837 | bool HiPlayer::slotResolveLrc(const QString & source_file_name)//根据歌曲文件名解析本地lrc歌词 838 | { 839 | lrcMap.clear(); 840 | if(source_file_name.isEmpty()) 841 | return false; 842 | QString file_name = source_file_name; 843 | QString lrc_file_name = file_name.remove(file_name.right(3)) + "lrc";//把音频文件的后缀改成lrc后缀 844 | 845 | // 打开歌词文件 846 | QFile file(lrc_file_name); 847 | if(!file.open(QIODevice::ReadOnly)) 848 | return false; 849 | 850 | QByteArray temp = file.readAll(); 851 | QByteArray temp_text; 852 | for (int i = 0; i < temp.size(); i++) 853 | { 854 | if (temp.at(i) != 0) 855 | temp_text.append(temp.at(i));//去掉temp中的空格 856 | } 857 | 858 | QString all_text = QString::fromUtf8(temp_text); 859 | 860 | file.close(); 861 | // 将歌词按行分解为歌词列表 862 | QStringList lines = all_text.split("\n"); 863 | 864 | //这个是时间标签的格式[00:05.54]----[mm:ss.ff](分钟数:秒数.百分之一秒数 ) 865 | //正则表达式\d{2}表示匹配2个数字 866 | QRegExp rx("\\[\\d{2}:\\d{2}\\.\\d{2}\\]");//实际的正则表达式为\[\d{2}:\d{2}\.\d{2}\] 867 | foreach(QString oneline, lines)//对歌词内容逐行操作 868 | { 869 | QString text = oneline; 870 | text.replace(rx, "");//用空字符串替换正则表达式中所匹配的地方,这样就获得了歌词文本 871 | // 然后依次获取当前行中的所有时间标签,并分别与歌词文本存入QMap中 872 | //indexIn()为返回第一个匹配的位置,如果返回为-1,则表示没有匹配成功 873 | //正常情况下pos后面应该对应的是歌词文件 874 | int pos = rx.indexIn(oneline, 0); 875 | //qDebug()<<"POS="<hi_setLyricText(mediaPlayer->metaData(QMediaMetaData::Title).toString()); 902 | return false; 903 | } 904 | 905 | return true; 906 | } 907 | 908 | //在文件不存在的情况下, 909 | //WriteOnly模式打开文件会创建新的空白文件 910 | //ReadOnly模式打开文件则不会创建新的空白文件,会打开失败. 911 | 912 | void HiPlayer::slotReadList()//读取本地保存的记录歌曲列表的文件 913 | { 914 | QFile text(dirPath + "/HiPlayerList.list"); 915 | QStringList inList; 916 | 917 | if(text.open(QIODevice::ReadOnly)){ 918 | QDataStream in(&text); 919 | in.setVersion(QDataStream::Qt_5_8); 920 | in >> inList; 921 | hi_addList(inList); 922 | text.close(); 923 | }else 924 | { 925 | qDebug()<<"list file open error:"<setCurrentIndex(playList.indexOf(filePath)); 956 | mediaPlayer->play(); 957 | } 958 | } 959 | 960 | void HiPlayer::hi_setTableColor()//设置列表颜色交替 961 | { 962 | for (int i = 0; i < playlistTable->rowCount(); i++) 963 | { 964 | 965 | if (i % 2 == 0){ 966 | for (int j = 0; j < playlistTable->columnCount(); j++){ 967 | QTableWidgetItem *item = playlistTable->item(i, j); 968 | if (item){ 969 | const QColor color = QColor(255, 255, 255); 970 | item->setBackgroundColor(color);//设置深色背景 971 | } 972 | } 973 | } 974 | else{ 975 | for (int j = 0; j < playlistTable->columnCount(); j++) 976 | { 977 | QTableWidgetItem *item = playlistTable->item(i, j); 978 | if (item){ 979 | const QColor color = QColor(213, 228, 242); 980 | item->setBackgroundColor(color);//设置白色背景 981 | } 982 | } 983 | } 984 | } 985 | } 986 | 987 | void HiPlayer::hi_initNetwork()//初始化网络模块 988 | { 989 | networker = NetWorker::getInstance(); 990 | receiveState = RECEIVE_INFO; 991 | /* lambda表达式 992 | 1.[var]表示值传递方式捕捉变量var; 993 | 2.[=]表示值传递方式捕捉所有父作用域的变量(包括this); 994 | 3.[&var]表示引用传递捕捉变量var; 995 | 4.[&]表示引用传递方式捕捉所有父作用域的变量(包括this); 996 | 5.[this]表示值传递方式捕捉当前的this指针。 997 | */ 998 | connect(networker, &NetWorker::finished, [&](QNetworkReply *reply) { 999 | switch (receiveState){ 1000 | case RECEIVE_INFO: 1001 | hi_recvInfo(reply); 1002 | hi_fetchNetData(); 1003 | break; 1004 | case RECEIVE_LINK: 1005 | hi_recvLink(reply); 1006 | hi_fetchNetData(); 1007 | break; 1008 | case RECEIVE_PIC: 1009 | hi_recvPic(reply); 1010 | hi_fetchNetData(); 1011 | break; 1012 | case RECEIVE_LRC: 1013 | hi_recvLrc(reply); 1014 | receiveState = RECEIVE_INFO; 1015 | break; 1016 | default: 1017 | break; 1018 | } 1019 | reply->abort(); 1020 | }); 1021 | } 1022 | 1023 | void HiPlayer::hi_fetchNetData() //根据不同的标志获取不同的网络数据 1024 | { 1025 | qDebug()<<"hi_fetchNetData()"; 1026 | QString query = QUrl::toPercentEncoding(songName + " " + songArtist); 1027 | switch (receiveState) 1028 | { 1029 | case RECEIVE_INFO: 1030 | networker->get( 1031 | QString("http://tingapi.ting.baidu.com/v1/restserver/ting?format=json&calback=&from=webapp_music&method=baidu.ting.search.catalogSug&query=" + 1032 | query )); 1033 | break; 1034 | case RECEIVE_LINK: 1035 | //networker->get(QString("http://ting.baidu.com/data/music/links?songIds=" + songId)); 1036 | networker->get(QString("http://music.baidu.com/data/music/links?songIds=" + 1037 | songId)); 1038 | break; 1039 | case RECEIVE_PIC: 1040 | networker->get(picUrl); 1041 | break; 1042 | case RECEIVE_LRC: 1043 | qDebug()<<"lrcUrl:"<get(lrcUrl); 1045 | break; 1046 | default: 1047 | break; 1048 | } 1049 | } 1050 | 1051 | void HiPlayer::hi_recvInfo(QNetworkReply *reply)//接收歌曲信息,主要是获取歌曲id 1052 | { 1053 | QJsonParseError Jsonerror; 1054 | QJsonDocument jsonDocument = QJsonDocument::fromJson(reply->readAll(), &Jsonerror); 1055 | if (Jsonerror.error == QJsonParseError::NoError) 1056 | { 1057 | if (!(jsonDocument.isNull() || jsonDocument.isEmpty()) && jsonDocument.isObject()) 1058 | { 1059 | //QVariantMap----QMap 1060 | QVariantMap data = jsonDocument.toVariant().toMap(); 1061 | SongInfo song; 1062 | song.set_order(data[QLatin1String("order")].toString()); 1063 | song.set_error_code(data[QLatin1String("error_code")].toString()); 1064 | 1065 | //QVariantList----QList 1066 | QVariantList result_list = data[QLatin1String("song")].toList(); 1067 | QVariantList album_list = data[QLatin1String("album")].toList(); 1068 | 1069 | if (result_list.size() == 0){ 1070 | qDebug()<<"未找到搜索结果"; 1071 | return; 1072 | } 1073 | 1074 | QList results; 1075 | foreach(QVariant s, result_list){ 1076 | QVariantMap sm = s.toMap(); 1077 | SongResult *result = new SongResult; 1078 | result->set_songid(sm[QLatin1String("songid")].toString()); 1079 | result->set_songname(sm[QLatin1String("songname")].toString()); 1080 | result->set_has_mv(sm[QLatin1String("has_mv")].toInt()); 1081 | result->set_yyr_artist(sm[QLatin1String("yyr_artist")].toInt()); 1082 | result->set_artistname(sm[QLatin1String("artistname")].toString()); 1083 | results.append(result); 1084 | } 1085 | song.set_song_results(results); 1086 | 1087 | QList album_infos; 1088 | foreach(QVariant a, album_list) 1089 | { 1090 | QVariantMap ai = a.toMap(); 1091 | AlbumInfo *info = new AlbumInfo; 1092 | info->set_albumid(ai[QLatin1String("albumid")].toString()); 1093 | info->set_albumname(ai[QLatin1String("albumname")].toString()); 1094 | info->set_artistname(ai[QLatin1String("artistname")].toString()); 1095 | info->set_artistpic(ai[QLatin1String("artistpic")].toString()); 1096 | album_infos.append(info); 1097 | } 1098 | song.set_album_infos(album_infos); 1099 | 1100 | if (results.count() > 0){ 1101 | SongResult *temp = new SongResult; 1102 | temp = results[0]; 1103 | 1104 | songId = temp->get_songid(); 1105 | qDebug()<<"founded songId:"<deleteLater(); 1111 | } 1112 | 1113 | void HiPlayer::hi_recvLink(QNetworkReply *reply)//接收歌词地址 1114 | { 1115 | QJsonParseError error; 1116 | QJsonDocument jsonDocument = QJsonDocument::fromJson(reply->readAll(), &error); 1117 | if (error.error == QJsonParseError::NoError) 1118 | { 1119 | if (!(jsonDocument.isNull() || jsonDocument.isEmpty()) && jsonDocument.isObject()) { 1120 | QVariantMap data = jsonDocument.toVariant().toMap(); 1121 | 1122 | SongLink link; 1123 | link.set_errorcode(data[QLatin1String("errorCode")].toString()); 1124 | 1125 | QVariantMap song_data_map = data[QLatin1String("data")].toMap(); 1126 | 1127 | SongData sdata; 1128 | sdata.set_xcode(song_data_map[QLatin1String("xcode")].toString()); 1129 | 1130 | QList slist = song_data_map[QLatin1String("songList")].toList(); 1131 | QList slists; 1132 | foreach(QVariant s, slist) 1133 | { 1134 | QVariantMap sl = s.toMap(); 1135 | SongList *list = new SongList; 1136 | list->set_songpic_radio(sl[QLatin1String("songPicRadio")].toString()); 1137 | list->set_lrclink(sl[QLatin1String("lrcLink")].toString()); 1138 | slists.append(list); 1139 | } 1140 | sdata.set_song_lists(slists); 1141 | link.set_song_data(sdata); 1142 | 1143 | SongData temp2 = link.get_song_data(); 1144 | QList temp3 = temp2.get_song_lists(); 1145 | if (temp3.count() > 0) 1146 | { 1147 | SongList *templist = temp3[0]; 1148 | picUrl = templist->get_songpic_radio();//获取专辑图片网址 1149 | qDebug()<<"founded songpic_radio:"<get_lrclick();//获取歌词网址 1151 | qDebug()<<"founded lrclick:"<deleteLater(); 1157 | } 1158 | 1159 | void HiPlayer::hi_recvLrc(QNetworkReply *reply)//接收网络歌词,保存歌词文件 1160 | { 1161 | if (reply->error() == QNetworkReply::NoError) 1162 | { 1163 | QByteArray data = reply->readAll(); 1164 | qDebug()<<"founded lrc data:"<open(QIODevice::WriteOnly)) { 1171 | delete file; 1172 | file = 0; 1173 | return; 1174 | } 1175 | 1176 | QDataStream out(file); 1177 | out << data; 1178 | file->close(); 1179 | delete file; 1180 | file = 0; 1181 | } 1182 | reply->deleteLater(); 1183 | 1184 | slotResolveLrc(playingFile); 1185 | } 1186 | 1187 | void HiPlayer::hi_recvPic(QNetworkReply *reply)//接收专辑图片 1188 | { 1189 | if (reply->error() == QNetworkReply::NoError) 1190 | { 1191 | QByteArray data = reply->readAll(); 1192 | if (data.size() < 50)//未获取到图片,直接跳过去获取歌词 1193 | { 1194 | qDebug()<<"未收到正确的图片!"; 1195 | receiveState = RECEIVE_LRC; 1196 | return; 1197 | } 1198 | QPixmap currentPicture; 1199 | 1200 | if (currentPicture.loadFromData(data)){ 1201 | picLabel->setPixmap(currentPicture); 1202 | } 1203 | 1204 | receiveState = RECEIVE_LRC; 1205 | 1206 | QString temp = playingFile; 1207 | QString fileName = temp.remove(temp.right(3)) + "jpg"; 1208 | currentPicture.save(fileName);//将图片保存到文件中 1209 | } 1210 | reply->deleteLater(); 1211 | } 1212 | 1213 | bool HiPlayer::hi_getPicFromFile() //从磁盘中读取专辑图片 1214 | { 1215 | if (playingFile.isEmpty()) 1216 | return false; 1217 | QString file_name = playingFile; 1218 | QString pic_file_name = file_name.remove(file_name.right(3)) + "jpg";//把音频文件的后缀改成jpg后缀 1219 | 1220 | // 打开图片文件 1221 | QFile file(pic_file_name); 1222 | if (!file.open(QIODevice::ReadOnly)) 1223 | return false; 1224 | QByteArray temp = file.readAll(); 1225 | QPixmap currentPicture; 1226 | 1227 | if (currentPicture.loadFromData(temp)) 1228 | { 1229 | picLabel->setPixmap(currentPicture); 1230 | } 1231 | file.close(); 1232 | return true; 1233 | } 1234 | 1235 | void HiPlayer::closeEvent(QCloseEvent *) //窗口关闭之前需要的操作 1236 | { 1237 | slotWriteList(); 1238 | } 1239 | 1240 | 1241 | void HiPlayer::slotSetPlayPosition(int pos) 1242 | { 1243 | playPosition = pos; 1244 | } 1245 | 1246 | int HiPlayer::slotGetPlayPosition() 1247 | { 1248 | return playPosition; 1249 | } 1250 | 1251 | void HiPlayer::mousePressEvent(QMouseEvent *event) 1252 | { 1253 | m_Moveing=true; 1254 | //记录下鼠标相对于窗口的位置 1255 | //event->globalPos()鼠标按下时,鼠标相对于整个屏幕位置 1256 | //pos() this->pos()鼠标按下时,窗口相对于父窗口的位置 1257 | m_MovePosition=event->globalPos() - pos(); 1258 | //event->accept(); 1259 | return QWidget::mousePressEvent(event); 1260 | } 1261 | 1262 | void HiPlayer::mouseMoveEvent(QMouseEvent *event) 1263 | { 1264 | //(event->buttons() && Qt::LeftButton)按下是左键 1265 | //鼠标移动事件需要移动窗口,窗口移动到哪里呢?就是要获取鼠标移动中,窗口在整个屏幕的坐标,然后move到这个坐标,怎么获取坐标? 1266 | //通过事件event->globalPos()知道鼠标坐标,鼠标坐标减去鼠标相对于窗口位置,就是窗口在整个屏幕的坐标 1267 | if (m_Moveing && (event->buttons() && Qt::LeftButton) 1268 | && (event->globalPos()-m_MovePosition).manhattanLength() > QApplication::startDragDistance()) 1269 | { 1270 | move(event->globalPos()-m_MovePosition);//相对于桌面的位置. 1271 | m_MovePosition = event->globalPos() - pos(); 1272 | } 1273 | return QWidget::mouseMoveEvent(event); 1274 | //event->accept(); 1275 | } 1276 | 1277 | void HiPlayer::mouseReleaseEvent(QMouseEvent *) 1278 | { 1279 | m_Moveing=false; 1280 | } 1281 | 1282 | void HiPlayer::slotRecvMessage(QString message) 1283 | { 1284 | qDebug()<<"Tips:"<showNormal(); 1286 | this->raise(); 1287 | this->activateWindow(); 1288 | } 1289 | -------------------------------------------------------------------------------- /hiplayer.h: -------------------------------------------------------------------------------- 1 | #ifndef HIPLAYER_H 2 | #define HIPLAYER_H 3 | 4 | 5 | //文字滚动速度 6 | #define TEXT_SPEED 500 7 | 8 | #include "hiLrcWidget.h" 9 | #include "hiButton.h" 10 | #include "aboutDialog.h" 11 | #include "hiVolBotton.h" 12 | #include "hiLabel.h" 13 | #include "nofocusdelegate.h" 14 | #include "network.h" 15 | #include "songinfo.h" 16 | #include "playslider.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | //枚举播放模式 32 | enum Play_Mode{SINGAL, LISTCIRCLE, SINGALCIRCLE, RANDOM}; 33 | 34 | //网络音乐信息,专辑图片,歌词获取状态 35 | //网络歌词、专辑图片获取(保存在歌曲目录下,文件名与歌曲同名) 36 | enum { RECEIVE_INFO, RECEIVE_LINK, RECEIVE_PIC, RECEIVE_LRC }; 37 | 38 | class MiniWindow; 39 | 40 | class HiPlayer : public QWidget 41 | { 42 | //设置mini窗口类为主窗口类的友元类,从而可以调用主窗口类的私有函数和私有对象 43 | friend class MiniWindow; 44 | 45 | Q_OBJECT 46 | 47 | public: 48 | explicit HiPlayer(QWidget *parent = 0); 49 | ~HiPlayer(); 50 | 51 | //通过命令行打开指定音乐文件 52 | void hi_openMusic(const QString& filePath); 53 | 54 | public slots: 55 | 56 | //接受mini窗口传来的参数设置播放模式 57 | void slotSetModeFromMini(int mode); 58 | 59 | //接受mini窗口传来的参数设置音量 60 | void slotSetVolFromMini(int val); 61 | 62 | public slots: 63 | 64 | //访问目录结构 65 | void slotOpenDir(); 66 | 67 | //添加mp3格式的文件 68 | void slotOpenMusic(); 69 | 70 | //删除指定行的歌曲 71 | void slotRemoveCurrentMusic(); 72 | 73 | //清空播放列表 74 | void slotClearList(); 75 | 76 | //请求右键菜单 77 | void slotPlaylistMenuRequested(const QPoint &pos); 78 | 79 | //双击播放歌曲 80 | void slotPlaylistDoubleClicked(int row, int); 81 | 82 | //更新音乐信息 83 | void slotUpdateMetaData(); 84 | 85 | //更新进度条 86 | void slotUpdateProcessbar(qint64 duration); 87 | 88 | //更新播放状态 89 | void slotUpdateState(QMediaPlayer::State state); 90 | 91 | //更新播放进度 92 | void slotSetPosition(/*int position*/); 93 | 94 | //更新歌词、时间显示 95 | void slotUpdatePosition(qint64 position); 96 | 97 | //设置各按钮的单击事件,激活各按钮 98 | void slotPlayButtonClicked(); 99 | void slotLyricButtonClicked(); 100 | void slotLogoButtonClicked(); 101 | void slotModeButtonClicked(); 102 | void slotPauseButtonClicked(); 103 | void slotMinButtonClicked(); 104 | void slotNextButtonClicked(); 105 | void slotLastButtonClicked(); 106 | 107 | //设置播放模式 108 | void slotSetPlayMode(); 109 | 110 | //解析LRC歌词 111 | bool slotResolveLrc(const QString &source_file_name); 112 | 113 | //程序打开时读取播放列表文件 114 | void slotReadList(); 115 | 116 | //把现有播放列表写入列表文件 117 | void slotWriteList(); 118 | 119 | //设置当前播放位置 120 | void slotSetPlayPosition(int pos); 121 | 122 | //获取当前播放位置 123 | int slotGetPlayPosition(); 124 | 125 | //处理鼠标点击PlaySlider的信号 126 | void slotSliderValueClicked(int value); 127 | 128 | //实现只允许唯一程序执行 129 | void slotRecvMessage(QString message); 130 | protected: 131 | void closeEvent(QCloseEvent *event); //窗口关闭之前需要的操作 132 | private: 133 | 134 | //绘制窗体(也用于窗口位置拖动) 135 | void paintEvent(QPaintEvent *event); 136 | 137 | //拖拽添加,拖拽加歌现在可以一次性添加多首,且可以自动识别文件类型,只添加mp3文件 . 138 | void dragEnterEvent(QDragEnterEvent *event); 139 | void dropEvent(QDropEvent *event); 140 | 141 | //用于窗口位置拖动 142 | void mousePressEvent(QMouseEvent *event); 143 | void mouseMoveEvent(QMouseEvent *event); 144 | void mouseReleaseEvent(QMouseEvent *event); 145 | 146 | //初始化主界面 147 | void hi_initUi(); 148 | 149 | //初始化播放模块 150 | void hi_initPlayer(); 151 | 152 | //初始化信号-槽连接 153 | void hi_initConnections(); 154 | 155 | //初始化窗口 156 | void hi_initWindows(); 157 | 158 | //初始化菜单项 159 | void hi_initMenuActions(); 160 | 161 | //添加到播放列表 162 | void hi_addList(QStringList list); 163 | 164 | //定制tablewidget外观 165 | void hi_setTableColor(); 166 | 167 | //初始化网络模块 168 | void hi_initNetwork(); 169 | 170 | //获取网络数据 171 | void hi_fetchNetData(); 172 | 173 | //接收专辑图片 174 | void hi_recvPic(QNetworkReply *reply); 175 | 176 | //接收歌曲信息 177 | void hi_recvInfo(QNetworkReply *reply); 178 | 179 | //接收网络歌词 180 | void hi_recvLrc(QNetworkReply *reply); 181 | 182 | //接收歌词地址 183 | void hi_recvLink(QNetworkReply *reply); 184 | 185 | //从磁盘中读取专辑图片 186 | bool hi_getPicFromFile(); 187 | 188 | 189 | private: 190 | HiLrcWidget *lrcWidget; 191 | QMap lrcMap; 192 | 193 | QStringList playList; 194 | QString playingFile; 195 | QString dirPath; 196 | 197 | HiButton *miniButton; 198 | HiButton *exitButton; 199 | HiButton *addButton; 200 | HiButton *lyricButton; 201 | HiButton *lastButton; 202 | HiButton *nextButton; 203 | HiButton *playButton; 204 | HiButton *pauseButton; 205 | HiButton *modeButton; 206 | HiButton *minButton; 207 | HiButton *logoButton; 208 | 209 | HiLabel *nameLabel; 210 | QLabel *musicianLabel; 211 | QLabel *albumLabel; 212 | QLabel *timeLabel; 213 | QLabel *picLabel; 214 | 215 | PlaySlider *playSlider; 216 | // QSlider *volSlider; 217 | 218 | QTableWidget *playlistTable; 219 | 220 | QMediaPlayer *mediaPlayer; 221 | QMediaPlaylist *mediaList; 222 | 223 | QMenu *contextMenuLess; 224 | QMenu *contextMenuMore; 225 | QMenu *playModeMenu; 226 | 227 | QActionGroup *modeActionGroup; 228 | 229 | //enum ICE_Play_Mode{SINGAL, LISTCIRCLE, SINGALCIRCLE, RANDOM}; 230 | QAction *modeSingal; 231 | QAction *modeListCircle; 232 | QAction *modeSingalCircle; 233 | QAction *modeRandom; 234 | QAction *addMusic; 235 | QAction *addFileDiv; 236 | QAction *removeCurr; 237 | QAction *removeAll; 238 | 239 | HiVolBotton *volButton; 240 | 241 | MiniWindow * miniForm; 242 | AboutDialog *aboutForm; 243 | 244 | NetWorker * networker; 245 | QString songName; 246 | QString songArtist; 247 | QString songId; 248 | QString picUrl; 249 | QString lrcUrl; 250 | 251 | //int preIndex;//未使用 252 | int currentIndex;//当前播放歌曲在列表中的index 253 | int playMode;//当前播放模式 254 | 255 | int receiveState;//接收状态 256 | int playPosition;//当前歌曲播放位置 257 | 258 | //用于窗口位置拖动 259 | bool m_Moveing; 260 | QPoint m_MovePosition; 261 | }; 262 | 263 | #endif // HIPLAYER_H 264 | -------------------------------------------------------------------------------- /icon.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | resources/about.png 4 | resources/addMusic_40_40.png 5 | resources/HiPlayer_16_16_2.png 6 | resources/HiPlayer_32_32_2.png 7 | resources/HiPlayer_38_38.png 8 | resources/HiPlayer_48_48_2.png 9 | resources/HiPlayer_80_80_2.png 10 | resources/HiPlayer_256_256_2.png 11 | resources/Last_40_40.png 12 | resources/Lyric_40_40.png 13 | resources/mode.png 14 | resources/Next_40_40.png 15 | resources/Pause_60_60.png 16 | resources/Pause_100_100.png 17 | resources/Play_60_60.png 18 | resources/Play_100_100.png 19 | resources/Volumn_40_40.png 20 | resources/background.png 21 | resources/default_album.jpg 22 | resources/关闭.png 23 | resources/缩小.png 24 | resources/最小化.png 25 | resources/lrc_background.png 26 | resources/album.png 27 | resources/播放按钮mini.png 28 | resources/mini_back.png 29 | resources/play_mini.png 30 | resources/pause_mini.png 31 | resources/max_mini.png 32 | resources/next_mini.png 33 | resources/last_mini.png 34 | 35 | 36 | -------------------------------------------------------------------------------- /lrcLabel.cpp: -------------------------------------------------------------------------------- 1 | #include "lrcLabel.h" 2 | 3 | LrcLabel::LrcLabel(QWidget *parent) 4 | : HiLabel(parent) 5 | { 6 | setText(QString::fromUtf8("HiPlayer")); 7 | // 固定显示区域大小 8 | setMaximumSize(800, 60); 9 | setMinimumSize(800, 60); 10 | 11 | //歌词的线性渐变填充 12 | linearGradient.setStart(0, 10);//填充的起点坐标 13 | linearGradient.setFinalStop(0, 40);//填充的终点坐标 14 | //第一个参数终点坐标,相对于我们上面的区域而言,按照比例进行计算 15 | linearGradient.setColorAt(0.1, QColor(0, 148, 255)); 16 | linearGradient.setColorAt(0.5, QColor(114, 232, 255)); 17 | linearGradient.setColorAt(0.9, QColor(0, 148, 255)); 18 | 19 | 20 | // 遮罩的线性渐变填充 21 | maskLinearGradient.setStart(0, 0); 22 | maskLinearGradient.setFinalStop(0, 40); 23 | maskLinearGradient.setColorAt(0.1, QColor(222, 54, 4)); 24 | maskLinearGradient.setColorAt(0.5, QColor(255, 72, 16)); 25 | maskLinearGradient.setColorAt(0.9, QColor(222, 54, 4)); 26 | 27 | // 设置字体 28 | lrcFont.setFamily(QString::fromUtf8("微软雅黑")); 29 | //lrcFont.setBold(true);//字体加粗 30 | lrcFont.setPointSize(25); 31 | 32 | // 设置定时器 33 | lrcTimer = new QTimer(this); 34 | connect(lrcTimer, SIGNAL(timeout()), this, SLOT(slotTimeout())); 35 | lrcMaskWidth = 0; 36 | lrcMaskWidthInterval = 0; 37 | } 38 | 39 | // 开启遮罩,需要指定当前歌词开始与结束之间的时间间隔(ms) 40 | void LrcLabel::hi_startLrcMask(qint64 intervaltime) 41 | { 42 | // 这里设置每隔30毫秒更新一次遮罩的宽度,因为如果更新太频繁 43 | // 会增加CPU占用率,而如果时间间隔太大,则动画效果就不流畅了 44 | qreal count = intervaltime / 30; 45 | //获取遮罩每次需要增加的宽度,这里的800是部件的固定宽度 46 | lrcMaskWidthInterval = 800 / count; 47 | lrcMaskWidth = 0; 48 | lrcTimer->start(30); 49 | } 50 | 51 | void LrcLabel::hi_stopLrcMask() 52 | { 53 | lrcTimer->stop(); 54 | lrcMaskWidth = 0; 55 | update(); 56 | } 57 | 58 | void LrcLabel::paintEvent(QPaintEvent *) 59 | { 60 | 61 | QPainter painter(this); 62 | painter.setFont(lrcFont); 63 | 64 | if(text().size() < 2){ 65 | setText("Music..."); 66 | } 67 | QString tmp = text(); 68 | tmp.toUtf8(); 69 | QColor(0, 0, 0, 200);//90, 105, 115, 200 70 | // 先绘制底层文字,作为阴影,这样会使显示效果更加清晰,且更有质感 71 | painter.setPen(QColor(0, 0, 0, 200)); 72 | painter.drawText(31, 1, 800, 60, Qt::AlignLeft, tmp); 73 | 74 | // 再在上面绘制渐变文字 75 | painter.setPen(QPen(linearGradient, 0)); 76 | painter.drawText(30, 0, 800, 60, Qt::AlignLeft, tmp); 77 | 78 | // 设置歌词遮罩 79 | painter.setPen(QPen(maskLinearGradient, 0)); 80 | painter.drawText(30, 0, lrcMaskWidth+30, 60, Qt::AlignLeft, tmp); 81 | } 82 | 83 | 84 | //右击事件 85 | void LrcLabel::contextMenuEvent(QContextMenuEvent *event) 86 | { 87 | QMenu menu; 88 | menu.addAction(QString::fromUtf8("隐藏"), this->parent(), SLOT(hide())); 89 | menu.exec(event->globalPos());//globalPos()为当前鼠标的位置坐标 90 | } 91 | 92 | 93 | void LrcLabel::slotTimeout() 94 | { 95 | 96 | //每隔一段固定的时间笼罩的长度就增加一点 97 | lrcMaskWidth += lrcMaskWidthInterval; 98 | update();//更新widget,但是并不立即重绘,而是安排一个Paint事件,当返回主循环时由系统来重绘 99 | } 100 | 101 | void LrcLabel::hi_setFontSize(int size)//设置字体 102 | { 103 | lrcFont.setPointSize(size); 104 | } 105 | -------------------------------------------------------------------------------- /lrcLabel.h: -------------------------------------------------------------------------------- 1 | #ifndef LRCLABEL_H 2 | #define LRCLABEL_H 3 | 4 | #include 5 | #include "hiLabel.h" 6 | 7 | //带有歌词遮罩的label 8 | class LrcLabel : public HiLabel 9 | { 10 | 11 | Q_OBJECT 12 | public: 13 | explicit LrcLabel(QWidget *parent = 0); 14 | 15 | //开始歌词遮罩 16 | void hi_startLrcMask(qint64 intervaltime); 17 | 18 | //停止歌词遮罩 19 | void hi_stopLrcMask(); 20 | 21 | //调整字体大小 22 | void hi_setFontSize(int size); 23 | 24 | protected: 25 | 26 | //绘制窗体 27 | void paintEvent(QPaintEvent *); 28 | 29 | //菜单事件 30 | void contextMenuEvent(QContextMenuEvent *event); 31 | 32 | private slots: 33 | 34 | void slotTimeout(); 35 | 36 | private: 37 | 38 | QLinearGradient linearGradient; 39 | QLinearGradient maskLinearGradient; 40 | QFont lrcFont; 41 | QTimer * lrcTimer; 42 | qreal lrcMaskWidth; 43 | qreal lrcMaskWidthInterval; 44 | QPoint offSet; 45 | }; 46 | 47 | #endif // LRCLABEL_H 48 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "singleApp.h" 2 | #include "hiplayer.h" 3 | 4 | #include 5 | 6 | //已添加的歌曲列表记录在文件HiPlayerList.list中 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | SingleApp app(argc, argv, "hiplayer"); 11 | 12 | if(app.isRunning()) 13 | { 14 | app.sendMessage("The program is running!"); 15 | return 0; 16 | } 17 | HiPlayer w; 18 | QObject::connect(&app,SIGNAL(sigMsgAvailable(QString)),&w,SLOT(slotRecvMessage(QString))); 19 | w.show(); 20 | 21 | return app.exec(); 22 | } 23 | -------------------------------------------------------------------------------- /miniWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "miniWindow.h" 2 | #include "hiplayer.h" 3 | 4 | MiniWindow::MiniWindow(HiPlayer *hiplayer,QWidget *parent):QWidget(parent) 5 | { 6 | mainWindow = hiplayer; 7 | 8 | setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); 9 | setAttribute(Qt::WA_TranslucentBackground); 10 | //半透明 11 | this->setWindowOpacity(0.9); 12 | 13 | //固定大小 14 | this->setFixedSize(100, 100); 15 | 16 | miniPlayButton = new HiButton( this); 17 | miniPlayButton->setObjectName(QStringLiteral("miniPlayButton")); 18 | miniPlayButton->setGeometry(QRect(35, 30, 33, 33)); 19 | 20 | miniPauseButton = new HiButton( this); 21 | miniPauseButton->setObjectName(QStringLiteral("miniPauseButton")); 22 | miniPauseButton->setGeometry(QRect(31, 30, 33, 33)); 23 | miniPauseButton->setVisible(false); 24 | 25 | miniNextButton = new HiButton( this); 26 | miniNextButton->setObjectName(QStringLiteral("nextButton")); 27 | miniNextButton->setGeometry(QRect(70, 64, 16, 16)); 28 | 29 | miniLastButton = new HiButton(this); 30 | miniLastButton->setObjectName(QStringLiteral("lastButton")); 31 | miniLastButton->setGeometry(QRect(8,57,12,12)); 32 | 33 | miniMaxButton=new HiButton(this); 34 | miniMaxButton->setObjectName(QStringLiteral("maxButton")); 35 | miniMaxButton->setGeometry(QRect(70,14,14,14)); 36 | 37 | //设置图标 38 | QIcon icon_play; 39 | icon_play.addFile(QStringLiteral(":/hiplayer/resources/play_mini.png")); 40 | miniPlayButton->hi_setButtonIcons(icon_play,icon_play); 41 | 42 | miniPlayButton->setIconSize(QSize(36,36)); 43 | miniPlayButton->setFlat(true); 44 | miniPlayButton->setFocusPolicy(Qt::NoFocus); 45 | miniPlayButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 46 | 47 | QIcon icon_pause; 48 | icon_pause.addFile(QStringLiteral(":/hiplayer/resources/pause_mini.png")); 49 | miniPauseButton->hi_setButtonIcons(icon_pause); 50 | 51 | miniPauseButton->setIconSize(QSize(36,36)); 52 | miniPauseButton->setFlat(true); 53 | miniPauseButton->setFocusPolicy(Qt::NoFocus); 54 | miniPauseButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 55 | 56 | QIcon icon_next; 57 | icon_next.addFile(QStringLiteral(":/hiplayer/resources/next_mini.png")); 58 | miniNextButton->hi_setButtonIcons(icon_next); 59 | 60 | miniNextButton->setIconSize(QSize(16,16)); 61 | miniNextButton->setFlat(true); 62 | miniNextButton->setFocusPolicy(Qt::NoFocus); 63 | miniNextButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 64 | 65 | QIcon icon_last; 66 | icon_last.addFile(QStringLiteral(":/hiplayer/resources/last_mini.png")); 67 | miniLastButton->hi_setButtonIcons(icon_last); 68 | 69 | miniLastButton->setIconSize(QSize(12,12)); 70 | miniLastButton->setFlat(true); 71 | miniLastButton->setFocusPolicy(Qt::NoFocus); 72 | miniLastButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 73 | 74 | QIcon icon_max; 75 | icon_max.addFile(QStringLiteral(":/hiplayer/resources/max_mini.png")); 76 | miniMaxButton->hi_setButtonIcons(icon_max); 77 | 78 | miniMaxButton->setIconSize(QSize(14,14)); 79 | miniMaxButton->setFlat(true); 80 | miniMaxButton->setFocusPolicy(Qt::NoFocus); 81 | miniMaxButton->setStyleSheet("QPushButton{background-color:rgba(255,255,255,0);border-style:solid;border-width:0px;border-color:rgba(255,255,255,0);}"); 82 | 83 | 84 | hi_initMenuActions(); 85 | connect(miniPlayButton, SIGNAL(clicked()), this, SLOT(slotPlay())); 86 | connect(miniPauseButton, SIGNAL(clicked()), this, SLOT(slotPause())); 87 | connect(miniNextButton, SIGNAL(clicked()), this, SLOT(slotNextMusic())); 88 | connect(miniLastButton,SIGNAL(clicked()),this,SLOT(slotLastMusic())); 89 | connect(miniMaxButton,SIGNAL(clicked()),this,SLOT(slotBackToMain())); 90 | } 91 | 92 | MiniWindow::~MiniWindow() 93 | { 94 | 95 | } 96 | 97 | void MiniWindow::paintEvent(QPaintEvent *event)//绘制窗体背景 98 | { 99 | qDebug()<<"paintEvent"; 100 | QPainter p(this); 101 | p.drawPixmap(0, 0 , QPixmap(":/hiplayer/resources/mini_back.png")); 102 | QWidget::paintEvent(event); 103 | } 104 | 105 | void MiniWindow::hi_initMenuActions()//设置右键菜单 106 | { 107 | mode0 = new QAction(QString::fromUtf8("单曲播放"), this); 108 | mode1 = new QAction(QString::fromUtf8("列表循环"), this); 109 | mode2 = new QAction(QString::fromUtf8("单曲循环"), this); 110 | mode3 = new QAction(QString::fromUtf8("随机播放"), this); 111 | 112 | modeGroup = new QActionGroup(this); 113 | modeGroup->addAction(mode0); 114 | modeGroup->addAction(mode1); 115 | modeGroup->addAction(mode2); 116 | modeGroup->addAction(mode3); 117 | 118 | mode0->setCheckable(true); 119 | mode1->setCheckable(true); 120 | mode2->setCheckable(true); 121 | mode3->setCheckable(true); 122 | mode0->setChecked(true); 123 | 124 | mainForm = new QAction(QString::fromUtf8("返回主界面"),this); 125 | next = new QAction(QString::fromUtf8("下一曲"),this); 126 | last = new QAction(QString::fromUtf8("上一曲"),this); 127 | lyric = new QAction(QString::fromUtf8("桌面歌词"), this); 128 | exit = new QAction(QString::fromUtf8("退出"),this); 129 | 130 | volSlider = new QSlider(Qt::Horizontal, this); 131 | volSlider->setRange(0, 100); 132 | volSlider->setGeometry(QRect(26,0,75,25)); 133 | connect(volSlider, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateVol(int))); 134 | 135 | volSlider->setStyleSheet("QSlider::groove:horizontal{border:0px;height:4px;}" 136 | "QSlider::sub-page:horizontal{background:#0096ff;}" 137 | "QSlider::add-page:horizontal{background:lightgray;} " 138 | "QSlider::handle:horizontal{background:white;width:10px;border:#51b5fb 10px;border-radius:5px;margin:-3px 0px -3px 0px;}"); 139 | 140 | setVolumn = new QWidgetAction(this); 141 | setVolumn->setDefaultWidget(volSlider); 142 | 143 | contextMenu = new QMenu(this); 144 | contextMenu->addAction(mainForm); 145 | contextMenu->addSeparator(); 146 | contextMenu->addAction(setVolumn); 147 | contextMenu->addSeparator(); 148 | contextMenu->addAction(next); 149 | contextMenu->addAction(last); 150 | contextMenu->addSeparator(); 151 | contextMenu->addActions(modeGroup->actions()); 152 | contextMenu->addSeparator(); 153 | contextMenu->addAction(lyric); 154 | contextMenu->addSeparator(); 155 | contextMenu->addAction(exit); 156 | 157 | contextMenu->setStyleSheet( 158 | "QMenu{padding:5px;background:white;border:1px solid gray;}" 159 | "QMenu::item{padding:0px 40px 0px 30px;height:25px;}" 160 | "QMenu::item:selected:enabled{background:#0096ff;color:white;}" 161 | "QMenu::item:selected:!enabled{background:transparent;}" 162 | "QMenu::separator{height:1px;background:lightgray;margin:5px 0px 5px 0px;}"); 163 | 164 | 165 | connect(mode0, SIGNAL(triggered()), this, SLOT(slotSetMode())); 166 | connect(mode1, SIGNAL(triggered()), this, SLOT(slotSetMode())); 167 | connect(mode2, SIGNAL(triggered()), this, SLOT(slotSetMode())); 168 | connect(mode3, SIGNAL(triggered()), this, SLOT(slotSetMode())); 169 | 170 | connect(mainForm, SIGNAL(triggered()), this, SLOT(slotBackToMain())); 171 | connect(next, SIGNAL(triggered()), this, SLOT(slotNextMusic())); 172 | connect(last, SIGNAL(triggered()), this, SLOT(slotLastMusic())); 173 | connect(lyric, SIGNAL(triggered()), this, SLOT(slotLyricAction())); 174 | connect(exit, SIGNAL(triggered()), this, SLOT(slotExit())); 175 | } 176 | 177 | void MiniWindow::hi_initPlayMode(int vol)//初始化播放模式和音量 178 | { 179 | switch(mainWindow->playMode){ 180 | case 0: 181 | mode0->setChecked(true); 182 | break; 183 | case 1: 184 | mode1->setChecked(true); 185 | break; 186 | case 2: 187 | mode2->setChecked(true); 188 | break; 189 | case 3: 190 | mode3->setChecked(true); 191 | break; 192 | } 193 | 194 | if(mainWindow->playButton->isVisible()){ 195 | miniPlayButton->setVisible(true); 196 | miniPauseButton->setVisible(false); 197 | } 198 | else { 199 | miniPlayButton->setVisible(false); 200 | miniPauseButton->setVisible(true); 201 | } 202 | 203 | volSlider->setValue(vol); 204 | } 205 | 206 | void MiniWindow::contextMenuEvent(QContextMenuEvent *)//鼠标右键触发 207 | { 208 | contextMenu->exec(QCursor::pos()); 209 | } 210 | 211 | void MiniWindow::slotExit() 212 | { 213 | mainWindow->close(); 214 | this->close(); 215 | } 216 | 217 | void MiniWindow::slotBackToMain() 218 | { 219 | mainWindow->show(); 220 | this->hide(); 221 | } 222 | 223 | void MiniWindow::slotNextMusic() 224 | { 225 | 226 | mainWindow->slotNextButtonClicked(); 227 | } 228 | 229 | void MiniWindow::slotLastMusic() 230 | { 231 | mainWindow->slotLastButtonClicked(); 232 | } 233 | 234 | void MiniWindow::slotPlay() 235 | { 236 | mainWindow->slotPlayButtonClicked(); 237 | miniPauseButton->setVisible(true); 238 | miniPlayButton->setVisible(false); 239 | } 240 | 241 | void MiniWindow::slotPause() 242 | { 243 | mainWindow->slotPauseButtonClicked(); 244 | miniPauseButton->setVisible(false); 245 | miniPlayButton->setVisible(true); 246 | } 247 | 248 | void MiniWindow::slotSetMode() 249 | { 250 | if(mode0->isChecked()) { 251 | mainWindow->slotSetModeFromMini(0); 252 | } 253 | else if(mode1->isChecked()) { 254 | mainWindow->slotSetModeFromMini(1); 255 | } 256 | else if(mode2->isChecked()) { 257 | mainWindow->slotSetModeFromMini(2); 258 | } 259 | else if(mode3->isChecked()) { 260 | mainWindow->slotSetModeFromMini(3); 261 | } 262 | } 263 | 264 | void MiniWindow::slotUpdateVol(int a) 265 | { 266 | mainWindow->slotSetVolFromMini(a); 267 | } 268 | 269 | void MiniWindow::slotLyricAction() 270 | { 271 | mainWindow->slotLyricButtonClicked(); 272 | } 273 | 274 | void MiniWindow::mousePressEvent(QMouseEvent *event) 275 | { 276 | m_Moveing=true; 277 | //记录下鼠标相对于窗口的位置 278 | //event->globalPos()鼠标按下时,鼠标相对于整个屏幕位置 279 | //pos() this->pos()鼠标按下时,窗口相对于父窗口的位置 280 | m_MovePosition=event->globalPos() - pos(); 281 | return QWidget::mousePressEvent(event); 282 | } 283 | 284 | void MiniWindow::mouseMoveEvent(QMouseEvent *event) 285 | { 286 | //(event->buttons() && Qt::LeftButton)按下是左键 287 | //鼠标移动事件需要移动窗口,窗口移动到哪里呢?就是要获取鼠标移动中,窗口在整个屏幕的坐标,然后move到这个坐标,怎么获取坐标? 288 | //通过事件event->globalPos()知道鼠标坐标,鼠标坐标减去鼠标相对于窗口位置,就是窗口在整个屏幕的坐标 289 | if (m_Moveing && (event->buttons() && Qt::LeftButton) 290 | && (event->globalPos()-m_MovePosition).manhattanLength() > QApplication::startDragDistance()) 291 | { 292 | move(event->globalPos()-m_MovePosition);//相对于桌面的位置. 293 | m_MovePosition = event->globalPos() - pos(); 294 | } 295 | return QWidget::mouseMoveEvent(event); 296 | } 297 | 298 | void MiniWindow::mouseReleaseEvent(QMouseEvent *) 299 | { 300 | m_Moveing=false; 301 | } 302 | 303 | -------------------------------------------------------------------------------- /miniWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MINIWINDOW_H 2 | #define MINIWINDOW_H 3 | 4 | #include 5 | #include "hiButton.h" 6 | //#include "hiplayer.h" 7 | 8 | class HiPlayer; 9 | 10 | class MiniWindow : public QWidget 11 | { 12 | Q_OBJECT 13 | public: 14 | MiniWindow(HiPlayer * hiplayer,QWidget *parent = 0); 15 | ~MiniWindow(); 16 | 17 | void hi_initPlayMode(int vol); 18 | 19 | 20 | private slots: 21 | void slotBackToMain(); 22 | 23 | void slotNextMusic(); 24 | 25 | void slotLastMusic(); 26 | 27 | void slotPlay(); 28 | 29 | void slotPause(); 30 | 31 | void slotSetMode(); 32 | 33 | void slotExit(); 34 | 35 | void slotLyricAction(); 36 | 37 | void slotUpdateVol(int); 38 | private: 39 | void paintEvent(QPaintEvent *event); 40 | void contextMenuEvent(QContextMenuEvent *event); 41 | 42 | void hi_initMenuActions(); 43 | 44 | //用于窗口位置拖动 45 | void mousePressEvent(QMouseEvent *event); 46 | void mouseMoveEvent(QMouseEvent *event); 47 | void mouseReleaseEvent(QMouseEvent *event); 48 | 49 | HiButton *miniPlayButton; 50 | HiButton *miniPauseButton; 51 | HiButton *miniNextButton; 52 | HiButton *miniLastButton; 53 | HiButton *miniMaxButton; 54 | 55 | QMenu *contextMenu; 56 | QActionGroup *modeGroup; 57 | QAction *mode0; 58 | QAction *mode1; 59 | QAction *mode2; 60 | QAction *mode3; 61 | QAction *mainForm; 62 | QAction *next; 63 | QAction *last; 64 | QAction *lyric; 65 | QAction *exit; 66 | 67 | QWidgetAction *setVolumn; 68 | QSlider *volSlider; 69 | 70 | HiPlayer *mainWindow; 71 | 72 | //用于窗口位置拖动 73 | bool m_Moveing; 74 | QPoint m_MovePosition; 75 | 76 | }; 77 | #endif // MINIWINDOW_H 78 | -------------------------------------------------------------------------------- /network.cpp: -------------------------------------------------------------------------------- 1 | #include "network.h" 2 | 3 | class NetWorker::Private 4 | { 5 | public: 6 | Private(NetWorker * q) 7 | : manager(new QNetworkAccessManager(q)) 8 | {} 9 | QNetworkAccessManager *manager; 10 | }; 11 | 12 | NetWorker * NetWorker::getInstance() 13 | { 14 | static NetWorker netWorker; 15 | return &netWorker; 16 | } 17 | 18 | NetWorker::NetWorker(QObject *parent ) 19 | : QObject(parent) 20 | , d(new NetWorker::Private(this)) 21 | { 22 | connect(d->manager, &QNetworkAccessManager::finished, this, 23 | &NetWorker::finished); 24 | } 25 | 26 | NetWorker::~NetWorker() 27 | { 28 | delete d; 29 | d = 0; 30 | } 31 | 32 | void NetWorker::get(const QString &url) 33 | { 34 | d->manager->get(QNetworkRequest(QUrl(url))); 35 | } 36 | -------------------------------------------------------------------------------- /network.h: -------------------------------------------------------------------------------- 1 | #ifndef NETWORK_H 2 | #define NETWORK_H 3 | 4 | //网络模块,实现网络功能 5 | //使用单例模式,封装网络接口 6 | //使用instance()获取唯一的NetWorker对象 7 | //使用内部类Private封装私有变量 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class NetWorker : public QObject 14 | { 15 | 16 | Q_OBJECT 17 | 18 | public: 19 | 20 | //获取唯一实例 21 | static NetWorker * getInstance(); 22 | 23 | ~NetWorker(); 24 | 25 | //向url发送get请求 26 | void get(const QString &url); 27 | 28 | signals: 29 | //操作完成后发射finished信号 30 | void finished(QNetworkReply *reply); 31 | 32 | private: 33 | class Private;//在类中定义另一个类 34 | friend class Private; 35 | Private * d; 36 | 37 | //使用单例模式,类的构造函数,复制构造函数和赋值运算符都声明为私有 38 | //若编译器支持c++ 11,Q_DECL_EQ_DELETE宏替换为 =delete 39 | explicit NetWorker(QObject *parent = 0); 40 | NetWorker(const NetWorker &) Q_DECL_EQ_DELETE; 41 | NetWorker &operator=(NetWorker rhs) Q_DECL_EQ_DELETE; 42 | //对于 C++ 的类,如果程序员没有为其定义特殊成员函数,那么 43 | //在需要用到某个特殊成员函数的时候,编译器会隐式的自动生成一个默认的特殊成员函数, 44 | //比如默认的构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。 45 | }; 46 | 47 | #endif // NETWORK_H 48 | -------------------------------------------------------------------------------- /nofocusdelegate.cpp: -------------------------------------------------------------------------------- 1 | #include "nofocusdelegate.h" 2 | 3 | void NoFocusDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const 4 | { 5 | QStyleOptionViewItem itemOption(option); 6 | if (itemOption.state & QStyle::State_HasFocus) 7 | itemOption.state = itemOption.state ^ QStyle::State_HasFocus; 8 | QStyledItemDelegate::paint(painter, itemOption, index); 9 | } 10 | -------------------------------------------------------------------------------- /nofocusdelegate.h: -------------------------------------------------------------------------------- 1 | #ifndef NOFOCUSDELEGATE_H 2 | #define NOFOCUSDELEGATE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class NoFocusDelegate : public QStyledItemDelegate{ 10 | 11 | protected: 12 | 13 | void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; 14 | }; 15 | 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /playslider.cpp: -------------------------------------------------------------------------------- 1 | #include "playslider.h" 2 | #include 3 | #include 4 | 5 | PlaySlider::PlaySlider(QWidget *parent) 6 | : QSlider(parent) 7 | { 8 | 9 | } 10 | void PlaySlider::mousePressEvent(QMouseEvent *event) 11 | { 12 | //注意应先调用父类的鼠标点击处理事件,这样可以不影响拖动的情况 13 | QSlider::mousePressEvent(event); 14 | //获取鼠标的位置,这里并不能直接从ev中取值(因为如果是拖动的话,鼠标开始点击的位置没有意义了) 15 | double pos = event->pos().x() / (double)width(); 16 | double value = pos * (maximum() - minimum()) + minimum(); 17 | //value + 0.5 四舍五入 18 | setValue(value + 0.5); 19 | emit sigValueClicked(this->value()); 20 | } 21 | -------------------------------------------------------------------------------- /playslider.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYSLIDER_H 2 | #define PLAYSLIDER_H 3 | 4 | #include 5 | 6 | class PlaySlider : public QSlider 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit PlaySlider(QWidget *parent = Q_NULLPTR); 11 | protected: 12 | void mousePressEvent(QMouseEvent *event);//实现鼠标点击改变滑块位置 13 | signals: 14 | void sigValueClicked(int value); 15 | public slots: 16 | }; 17 | 18 | #endif // PLAYSLIDER_H 19 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | **HiPlay** 是一款精致小巧的音乐播放器。 2 | 其主要功能如下: 3 | 添加本地歌曲到播放列表; 4 | 自动通过网络获取专辑图片和歌词; 5 | 歌词桌面显示,且带有歌词遮罩效果; 6 | Mini模式显示。 7 | 以下是部分软件截图: 8 | 播放器主界面: 9 | ![播放器主界面截图](http://img.blog.csdn.net/20180310162023177?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2xvbmczNjE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 10 | 歌词显示效果: 11 | ![歌词显示效果截图](http://img.blog.csdn.net/20180310162004419?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2xvbmczNjE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 12 | Mini窗口: 13 | ![Mini窗口截图](http://img.blog.csdn.net/20180310162226560?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2xvbmczNjE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 14 | About界面: 15 | ![About界面截图](http://img.blog.csdn.net/20180310162308711?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2xvbmczNjE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 16 | 17 | 18 | HiPlayer播放器基于Qt技术开发,作者开发环境为Qt5.8.0,MinGW5.3.0(32-bit),欢迎大家下载、讨论。 19 | 源代码下载地址:[HiPlayer播放器源代码Github下载地址](https://github.com/xiaolong361/HiPlayer) 20 | 21 | 可执行程序下载地址(绿色免安装):[HiPlayer播放器软件百度网盘下载地址](https://pan.baidu.com/s/17VScymfjDAfltKyH3KTxvA)   22 | -------------------------------------------------------------------------------- /resources/HiLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiLogo.png -------------------------------------------------------------------------------- /resources/HiLogo4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiLogo4.ico -------------------------------------------------------------------------------- /resources/HiLogo_2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiLogo_2.ico -------------------------------------------------------------------------------- /resources/HiPlayer_16_16_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiPlayer_16_16_2.png -------------------------------------------------------------------------------- /resources/HiPlayer_256_256_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiPlayer_256_256_2.png -------------------------------------------------------------------------------- /resources/HiPlayer_32_32_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiPlayer_32_32_2.png -------------------------------------------------------------------------------- /resources/HiPlayer_38_38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiPlayer_38_38.png -------------------------------------------------------------------------------- /resources/HiPlayer_48_48_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiPlayer_48_48_2.png -------------------------------------------------------------------------------- /resources/HiPlayer_80_80_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/HiPlayer_80_80_2.png -------------------------------------------------------------------------------- /resources/Last_40_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Last_40_40.png -------------------------------------------------------------------------------- /resources/Lyric_40_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Lyric_40_40.png -------------------------------------------------------------------------------- /resources/Next_40_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Next_40_40.png -------------------------------------------------------------------------------- /resources/Pause_100_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Pause_100_100.png -------------------------------------------------------------------------------- /resources/Pause_60_60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Pause_60_60.png -------------------------------------------------------------------------------- /resources/Play_100_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Play_100_100.png -------------------------------------------------------------------------------- /resources/Play_60_60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Play_60_60.png -------------------------------------------------------------------------------- /resources/Volumn_40_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/Volumn_40_40.png -------------------------------------------------------------------------------- /resources/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/about.png -------------------------------------------------------------------------------- /resources/addMusic_40_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/addMusic_40_40.png -------------------------------------------------------------------------------- /resources/album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/album.png -------------------------------------------------------------------------------- /resources/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/background.png -------------------------------------------------------------------------------- /resources/default_album.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/default_album.jpg -------------------------------------------------------------------------------- /resources/last_mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/last_mini.png -------------------------------------------------------------------------------- /resources/lrc_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/lrc_background.png -------------------------------------------------------------------------------- /resources/max_mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/max_mini.png -------------------------------------------------------------------------------- /resources/mini_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/mini_back.png -------------------------------------------------------------------------------- /resources/mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/mode.png -------------------------------------------------------------------------------- /resources/next_mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/next_mini.png -------------------------------------------------------------------------------- /resources/pause_mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/pause_mini.png -------------------------------------------------------------------------------- /resources/play_mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/play_mini.png -------------------------------------------------------------------------------- /resources/关闭.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/关闭.png -------------------------------------------------------------------------------- /resources/播放按钮mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/播放按钮mini.png -------------------------------------------------------------------------------- /resources/最小化.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/最小化.png -------------------------------------------------------------------------------- /resources/缩小.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaolong361/HiPlayer/441f1cab106a1c5c3f80c8cc07d6b286034e13ea/resources/缩小.png -------------------------------------------------------------------------------- /singleApp.cpp: -------------------------------------------------------------------------------- 1 | #include "singleApp.h" 2 | #include 3 | 4 | SingleApp::SingleApp(int &argc, char *argv[], const QString uniqueKey) 5 | : QApplication(argc, argv), _uniqueKey(uniqueKey) 6 | { 7 | _sharedMemory.setKey(_uniqueKey); 8 | if (_sharedMemory.attach())//读取数据,必须调用attach(),绑定_uniqueKey标志的共享内存区域 9 | _isRunning = true;//绑定成功,证明已经有进程创建了共享内存,有进程正在运行. 10 | else 11 | { 12 | _isRunning = false; 13 | // create shared memory. 14 | if (!_sharedMemory.create(1))//Creates a shared memory segment of 1 byte and attaches to the new shared memory segment 15 | { 16 | qDebug()<<"Unable to create single instance:"<<_sharedMemory.errorString().toLatin1(); 17 | return; 18 | } 19 | 20 | // create local server and listen to incomming messages from other instances. 21 | _localServer = new QLocalServer(this); 22 | connect(_localServer, SIGNAL(newConnection()), this, SLOT(receiveMessage())); 23 | _localServer->listen(_uniqueKey); 24 | } 25 | } 26 | 27 | // public slots. 28 | void SingleApp::receiveMessage() 29 | { 30 | QLocalSocket * localSocket = _localServer->nextPendingConnection(); 31 | if (!localSocket->waitForReadyRead(timeout)) 32 | { 33 | qDebug(localSocket->errorString().toLatin1()); 34 | return; 35 | } 36 | 37 | QByteArray byteArray = localSocket->readAll(); 38 | QString message = QString::fromUtf8(byteArray.constData()); 39 | emit sigMsgAvailable(message); 40 | localSocket->disconnectFromServer(); 41 | //qDebug()<<"receive message:"< 6 | #include 7 | #include 8 | 9 | class SingleApp : public QApplication{ 10 | Q_OBJECT 11 | public: 12 | 13 | SingleApp(int &argc, char *argv[], const QString uniqueKey); 14 | bool isRunning(); 15 | bool sendMessage(const QString &message); 16 | 17 | public slots: 18 | void receiveMessage(); 19 | 20 | signals: 21 | void sigMsgAvailable(QString message); 22 | private: 23 | static const int timeout = 1000; 24 | 25 | bool _isRunning; 26 | QString _uniqueKey; 27 | QSharedMemory _sharedMemory; 28 | QLocalServer * _localServer; 29 | 30 | }; 31 | #endif // SINGLEAPP_H 32 | -------------------------------------------------------------------------------- /songinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef SONG_INFO_H 2 | #define SONG_INFO_H 3 | 4 | #include 5 | #include 6 | 7 | class SongResult 8 | { 9 | public: 10 | SongResult(){} 11 | ~SongResult(){} 12 | 13 | void set_songid(QString songid){ 14 | _songid = songid; 15 | } 16 | QString get_songid(){ 17 | return _songid; 18 | } 19 | void set_songname(QString songname){ 20 | _songname = songname; 21 | } 22 | QString get_songname(){ 23 | return _songname; 24 | } 25 | void set_has_mv(int has_mv){ 26 | _has_mv = has_mv; 27 | } 28 | int get_has_mv(){ 29 | return _has_mv; 30 | } 31 | void set_yyr_artist(int yyr_artist){ 32 | _yyr_artist = yyr_artist; 33 | } 34 | int get_yyr_artist(){ 35 | return _yyr_artist; 36 | } 37 | void set_artistname(QString artistname){ 38 | _artistname = artistname; 39 | } 40 | QString get_artistname(){ 41 | return _artistname; 42 | } 43 | private: 44 | QString _songid; 45 | QString _songname; 46 | QString _encrypted_songid; 47 | int _has_mv; 48 | int _yyr_artist; 49 | QString _artistname; 50 | }; 51 | 52 | class AlbumInfo 53 | { 54 | public: 55 | AlbumInfo(){} 56 | ~AlbumInfo(){} 57 | 58 | void set_albumid(QString albumid){ 59 | _albumid = albumid; 60 | } 61 | QString get_albumid(){ 62 | return _albumid; 63 | } 64 | void set_albumname(QString albumname){ 65 | _albumname = albumname; 66 | } 67 | QString get_albumname(){ 68 | return _albumname; 69 | } 70 | void set_artistname(QString artistname){ 71 | _artistname = artistname; 72 | } 73 | QString get_artistname(){ 74 | return _artistname; 75 | } 76 | void set_artistpic(QString artistpic){ 77 | _artistpic = artistpic; 78 | } 79 | QString get_artistpic(){ 80 | return _artistpic; 81 | } 82 | private: 83 | QString _albumid; 84 | QString _albumname; 85 | QString _artistname; 86 | QString _artistpic; 87 | }; 88 | 89 | class SongInfo 90 | { 91 | public: 92 | SongInfo(){} 93 | ~SongInfo(){} 94 | 95 | void set_order(QString order){ 96 | _order = order; 97 | } 98 | QString get_order(){ 99 | return _order; 100 | } 101 | void set_error_code(QString error_code){ 102 | _error_code = error_code; 103 | } 104 | QString get_error_code(){ 105 | return _error_code; 106 | } 107 | void set_song_results(QList song_results){ 108 | _song_results = song_results; 109 | } 110 | QList get_song_results(){ 111 | return _song_results; 112 | } 113 | void set_album_infos(QList album_infos){ 114 | _album_infos = album_infos; 115 | } 116 | QList get_album_infos(){ 117 | return _album_infos; 118 | } 119 | private: 120 | QString _order; 121 | QString _error_code; 122 | 123 | QList _song_results; 124 | QList _album_infos; 125 | }; 126 | 127 | class SongList; 128 | class SongLink; 129 | 130 | class SongData 131 | { 132 | public: 133 | SongData(){} 134 | ~SongData(){} 135 | 136 | void set_xcode(QString xcode){ 137 | _xcode = xcode; 138 | } 139 | QString get_xcode(){ 140 | return _xcode; 141 | } 142 | void set_song_lists(QList song_lists){ 143 | _song_lists = song_lists; 144 | } 145 | QList get_song_lists(){ 146 | return _song_lists; 147 | } 148 | private: 149 | QString _xcode; 150 | QList _song_lists; 151 | }; 152 | 153 | class SongList{ 154 | public: 155 | SongList(){} 156 | ~SongList(){} 157 | 158 | void set_songpic_radio(QString songpic_radio){ 159 | _songpic_radio = songpic_radio; 160 | } 161 | 162 | QString get_songpic_radio(){ 163 | return _songpic_radio; 164 | } 165 | 166 | void set_lrclink(QString lrclink){ 167 | _lrclick = lrclink; 168 | } 169 | 170 | QString get_lrclick(){ 171 | return _lrclick; 172 | } 173 | 174 | private: 175 | QString _queryid; 176 | QString _songid; 177 | QString _songname; 178 | QString _artistid; 179 | QString _artistname; 180 | QString _albumid; 181 | QString _songpic_small; 182 | QString _songpic_big; 183 | QString _songpic_radio;// 184 | QString _lrclick;// 185 | QString _version; 186 | QString _copytype; 187 | QString _time; 188 | QString _linkcode; 189 | QString _songlink; 190 | QString _format; 191 | QString _rate; 192 | QString _size; 193 | QString _relatestatus; 194 | QString _resourcetype; 195 | 196 | }; 197 | 198 | class SongLink{ 199 | public: 200 | SongLink(){} 201 | ~SongLink(){} 202 | 203 | void set_errorcode(QString errorcode){ 204 | _errorcode = errorcode; 205 | } 206 | QString get_errorcode(){ 207 | return _errorcode; 208 | } 209 | void set_song_data(SongData sdata){ 210 | _song_datas = sdata; 211 | } 212 | SongData get_song_data(){ 213 | return _song_datas; 214 | } 215 | 216 | private: 217 | 218 | QString _errorcode; 219 | SongData _song_datas; 220 | 221 | }; 222 | 223 | #endif //SONG_INFO_H 224 | --------------------------------------------------------------------------------