Pyqt5 - 自制简易音乐播放器V1.0

 一:目的

(1)获取音乐文件,播放本地音乐,可切换音乐,暂停音乐,获取音乐播放总时间,选择单曲循环或者列表循环;

(2)自由设置音乐的音量;

(3)显示对应播放音乐的歌词;


演示:


二:利用QT-Tool,首先设计界面(UI)

(1)ui文件如下:music.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>685</width>
    <height>560</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="mouseTracking">
   <bool>true</bool>
  </property>
  <property name="tabletTracking">
   <bool>true</bool>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QFormLayout" name="formLayout">
    <item row="0" column="0">
     <widget class="QGroupBox" name="groupBox">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="maximumSize">
       <size>
        <width>180</width>
        <height>16777215</height>
       </size>
      </property>
      <property name="cursor">
       <cursorShape>ArrowCursor</cursorShape>
      </property>
      <property name="mouseTracking">
       <bool>false</bool>
      </property>
      <property name="layoutDirection">
       <enum>Qt::LeftToRight</enum>
      </property>
      <property name="autoFillBackground">
       <bool>false</bool>
      </property>
      <property name="title">
       <string>曲目</string>
      </property>
      <property name="alignment">
       <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
      </property>
      <property name="checkable">
       <bool>false</bool>
      </property>
      <layout class="QGridLayout" name="gridLayout_2">
       <property name="sizeConstraint">
        <enum>QLayout::SetDefaultConstraint</enum>
       </property>
       <item row="0" column="1">
        <widget class="QPushButton" name="pushButton">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>30</height>
          </size>
         </property>
         <property name="text">
          <string>上级</string>
         </property>
         <property name="checkable">
          <bool>false</bool>
         </property>
         <property name="checked">
          <bool>false</bool>
         </property>
        </widget>
       </item>
       <item row="2" column="0" colspan="2">
        <widget class="QListWidget" name="listWidget">
         <property name="minimumSize">
          <size>
           <width>160</width>
           <height>0</height>
          </size>
         </property>
         <property name="frameShape">
          <enum>QFrame::WinPanel</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Raised</enum>
         </property>
        </widget>
       </item>
       <item row="0" column="0">
        <widget class="QPushButton" name="device_ret">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>30</height>
          </size>
         </property>
         <property name="text">
          <string>音频设备</string>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
    <item row="0" column="1">
     <widget class="QGroupBox" name="groupBox_2">
      <property name="title">
       <string>播放显示</string>
      </property>
      <layout class="QGridLayout" name="gridLayout_3">
       <item row="3" column="0">
        <widget class="QPushButton" name="next_music">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>30</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>40</width>
           <height>40</height>
          </size>
         </property>
         <property name="text">
          <string/>
         </property>
         <property name="icon">
          <iconset>
           <activeoff>:/put1/IMG/按钮/下首按钮.png</activeoff>
          </iconset>
         </property>
         <property name="iconSize">
          <size>
           <width>40</width>
           <height>40</height>
          </size>
         </property>
        </widget>
       </item>
       <item row="3" column="2">
        <widget class="QPushButton" name="last_music">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>30</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>40</width>
           <height>40</height>
          </size>
         </property>
         <property name="baseSize">
          <size>
           <width>80</width>
           <height>80</height>
          </size>
         </property>
         <property name="styleSheet">
          <string notr="true">QPushButton {&quot;
              &quot;background-color: green;&quot;
                              &quot;font: bold 20px;&quot;	
                              &quot;border-width: 1px;&quot;	
                              &quot;border-radius: 40px;&quot; 
                              &quot;color: white;&quot;      
                              }</string>
         </property>
         <property name="text">
          <string/>
         </property>
         <property name="icon">
          <iconset>
           <activeoff>:/put1/IMG/按钮/上首按钮.png</activeoff>
          </iconset>
         </property>
         <property name="iconSize">
          <size>
           <width>40</width>
           <height>40</height>
          </size>
         </property>
        </widget>
       </item>
       <item row="0" column="0" colspan="10">
        <widget class="QLabel" name="jumpgif">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>40</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>16777215</width>
           <height>50</height>
          </size>
         </property>
         <property name="sizeIncrement">
          <size>
           <width>0</width>
           <height>0</height>
          </size>
         </property>
         <property name="baseSize">
          <size>
           <width>0</width>
           <height>0</height>
          </size>
         </property>
         <property name="frameShape">
          <enum>QFrame::Panel</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Sunken</enum>
         </property>
         <property name="text">
          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;展示GIF&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
        </widget>
       </item>
       <item row="2" column="8">
        <widget class="QLabel" name="timeshow">
         <property name="minimumSize">
          <size>
           <width>55</width>
           <height>0</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>60</width>
           <height>60</height>
          </size>
         </property>
         <property name="text">
          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;0:0/0:0&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
        </widget>
       </item>
       <item row="3" column="1">
        <widget class="QPushButton" name="play_stop_music">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>30</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>40</width>
           <height>40</height>
          </size>
         </property>
         <property name="styleSheet">
          <string notr="true"/>
         </property>
         <property name="text">
          <string/>
         </property>
         <property name="icon">
          <iconset>
           <activeon>:/put1/IMG/按钮/播放按钮.png</activeon>
          </iconset>
         </property>
         <property name="iconSize">
          <size>
           <width>40</width>
           <height>40</height>
          </size>
         </property>
         <property name="checkable">
          <bool>false</bool>
         </property>
         <property name="checked">
          <bool>false</bool>
         </property>
         <property name="autoRepeat">
          <bool>false</bool>
         </property>
         <property name="autoExclusive">
          <bool>false</bool>
         </property>
        </widget>
       </item>
       <item row="2" column="0" colspan="8">
        <widget class="QSlider" name="horizontalSlider">
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
         <property name="tickPosition">
          <enum>QSlider::NoTicks</enum>
         </property>
        </widget>
       </item>
       <item row="2" column="9" rowspan="2">
        <widget class="QLabel" name="label_3">
         <property name="styleSheet">
          <string notr="true">image: url(:/put1/IMG/独家.png);</string>
         </property>
         <property name="text">
          <string/>
         </property>
        </widget>
       </item>
       <item row="3" column="8">
        <widget class="QLabel" name="soundvalue">
         <property name="maximumSize">
          <size>
           <width>50</width>
           <height>50</height>
          </size>
         </property>
         <property name="text">
          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;0&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
        </widget>
       </item>
       <item row="3" column="6" colspan="2">
        <widget class="QSlider" name="verticalSlider">
         <property name="styleSheet">
          <string notr="true"/>
         </property>
         <property name="maximum">
          <number>100</number>
         </property>
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
        </widget>
       </item>
       <item row="3" column="3" colspan="2">
        <widget class="QComboBox" name="comboBox">
         <property name="minimumSize">
          <size>
           <width>0</width>
           <height>40</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>100</width>
           <height>16777215</height>
          </size>
         </property>
         <item>
          <property name="text">
           <string>单曲循环</string>
          </property>
          <property name="icon">
           <iconset>
            <activeon>:/put1/IMG/next.png</activeon>
           </iconset>
          </property>
         </item>
         <item>
          <property name="text">
           <string>列表循环</string>
          </property>
          <property name="icon">
           <iconset>
            <activeon>:/put1/IMG/循环.jpg</activeon>
           </iconset>
          </property>
         </item>
        </widget>
       </item>
       <item row="1" column="0" colspan="3">
        <widget class="QLabel" name="showgdance0">
         <property name="minimumSize">
          <size>
           <width>132</width>
           <height>0</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>16777215</width>
           <height>16777215</height>
          </size>
         </property>
         <property name="styleSheet">
          <string notr="true">background-color: rgb(208, 208, 208);</string>
         </property>
         <property name="frameShape">
          <enum>QFrame::WinPanel</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Raised</enum>
         </property>
         <property name="text">
          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;GIF跳动&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
        </widget>
       </item>
       <item row="1" column="8" colspan="2">
        <widget class="QLabel" name="showgdance1">
         <property name="minimumSize">
          <size>
           <width>132</width>
           <height>0</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>16777215</width>
           <height>16777215</height>
          </size>
         </property>
         <property name="styleSheet">
          <string notr="true">background-color: rgb(208, 208, 208);</string>
         </property>
         <property name="frameShape">
          <enum>QFrame::WinPanel</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Raised</enum>
         </property>
         <property name="text">
          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;GIF跳动&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
        </widget>
       </item>
       <item row="3" column="5">
        <widget class="QLabel" name="label">
         <property name="enabled">
          <bool>true</bool>
         </property>
         <property name="frameShape">
          <enum>QFrame::Panel</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Sunken</enum>
         </property>
         <property name="text">
          <string>音量设置:</string>
         </property>
        </widget>
       </item>
       <item row="1" column="3" colspan="5">
        <widget class="QScrollArea" name="scrollArea">
         <property name="widgetResizable">
          <bool>true</bool>
         </property>
         <widget class="QWidget" name="scrollAreaWidgetContents">
          <property name="geometry">
           <rect>
            <x>0</x>
            <y>0</y>
            <width>183</width>
            <height>343</height>
           </rect>
          </property>
          <layout class="QGridLayout" name="gridLayout">
           <item row="0" column="0">
            <widget class="QTextEdit" name="textEdit">
             <property name="maximumSize">
              <size>
               <width>16777215</width>
               <height>50</height>
              </size>
             </property>
             <property name="styleSheet">
              <string notr="true">background-color: rgba(255, 255, 255, 0.1);</string>
             </property>
             <property name="frameShape">
              <enum>QFrame::NoFrame</enum>
             </property>
             <property name="html">
              <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
             </property>
            </widget>
           </item>
           <item row="1" column="0">
            <widget class="QTextEdit" name="textEdit_2">
             <property name="maximumSize">
              <size>
               <width>16777215</width>
               <height>50</height>
              </size>
             </property>
             <property name="styleSheet">
              <string notr="true">background-color: rgba(255, 255, 255, 0.1);</string>
             </property>
             <property name="frameShape">
              <enum>QFrame::NoFrame</enum>
             </property>
             <property name="html">
              <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
             </property>
            </widget>
           </item>
           <item row="2" column="0">
            <widget class="QTextEdit" name="textEdit_3">
             <property name="maximumSize">
              <size>
               <width>16777215</width>
               <height>50</height>
              </size>
             </property>
             <property name="styleSheet">
              <string notr="true">background-color: rgba(255, 255, 255, 0.1);</string>
             </property>
             <property name="frameShape">
              <enum>QFrame::NoFrame</enum>
             </property>
             <property name="html">
              <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
             </property>
            </widget>
           </item>
           <item row="3" column="0">
            <widget class="QTextEdit" name="textEdit_4">
             <property name="maximumSize">
              <size>
               <width>16777215</width>
               <height>50</height>
              </size>
             </property>
             <property name="styleSheet">
              <string notr="true">background-color: rgba(255, 255, 255, 0.1);</string>
             </property>
             <property name="frameShape">
              <enum>QFrame::NoFrame</enum>
             </property>
             <property name="html">
              <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
             </property>
            </widget>
           </item>
           <item row="4" column="0">
            <widget class="QTextEdit" name="textEdit_5">
             <property name="maximumSize">
              <size>
               <width>16777215</width>
               <height>50</height>
              </size>
             </property>
             <property name="styleSheet">
              <string notr="true">background-color: rgba(255, 255, 255, 0.1);</string>
             </property>
             <property name="frameShape">
              <enum>QFrame::NoFrame</enum>
             </property>
             <property name="html">
              <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
             </property>
            </widget>
           </item>
          </layout>
         </widget>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>685</width>
     <height>23</height>
    </rect>
   </property>
   <widget class="QMenu" name="menu">
    <property name="title">
     <string>文件</string>
    </property>
   </widget>
   <addaction name="menu"/>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources>
  <include location="putton.qrc"/>
 </resources>
 <connections/>
</ui>

(2)ui文件转化为py文件:Ui_music.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'f:\personaldata\Python资料\Python_studyltem\自制音乐播放器0103\UI_files\music.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(685, 560)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMouseTracking(True)
        MainWindow.setTabletTracking(True)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.formLayout = QtWidgets.QFormLayout(self.centralwidget)
        self.formLayout.setObjectName("formLayout")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
        self.groupBox.setSizePolicy(sizePolicy)
        self.groupBox.setMaximumSize(QtCore.QSize(180, 16777215))
        self.groupBox.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.groupBox.setMouseTracking(False)
        self.groupBox.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.groupBox.setAutoFillBackground(False)
        self.groupBox.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
        self.groupBox.setCheckable(False)
        self.groupBox.setObjectName("groupBox")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)
        self.gridLayout_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.pushButton = QtWidgets.QPushButton(self.groupBox)
        self.pushButton.setMinimumSize(QtCore.QSize(0, 30))
        self.pushButton.setCheckable(False)
        self.pushButton.setChecked(False)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout_2.addWidget(self.pushButton, 0, 1, 1, 1)
        self.listWidget = QtWidgets.QListWidget(self.groupBox)
        self.listWidget.setMinimumSize(QtCore.QSize(160, 0))
        self.listWidget.setFrameShape(QtWidgets.QFrame.WinPanel)
        self.listWidget.setFrameShadow(QtWidgets.QFrame.Raised)
        self.listWidget.setObjectName("listWidget")
        self.gridLayout_2.addWidget(self.listWidget, 2, 0, 1, 2)
        self.device_ret = QtWidgets.QPushButton(self.groupBox)
        self.device_ret.setMinimumSize(QtCore.QSize(0, 30))
        self.device_ret.setObjectName("device_ret")
        self.gridLayout_2.addWidget(self.device_ret, 0, 0, 1, 1)
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.groupBox)
        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setObjectName("groupBox_2")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_2)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.next_music = QtWidgets.QPushButton(self.groupBox_2)
        self.next_music.setMinimumSize(QtCore.QSize(0, 30))
        self.next_music.setMaximumSize(QtCore.QSize(40, 40))
        self.next_music.setText("")
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/put1/IMG/按钮/下首按钮.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
        self.next_music.setIcon(icon)
        self.next_music.setIconSize(QtCore.QSize(40, 40))
        self.next_music.setObjectName("next_music")
        self.gridLayout_3.addWidget(self.next_music, 3, 0, 1, 1)
        self.last_music = QtWidgets.QPushButton(self.groupBox_2)
        self.last_music.setMinimumSize(QtCore.QSize(0, 30))
        self.last_music.setMaximumSize(QtCore.QSize(40, 40))
        self.last_music.setBaseSize(QtCore.QSize(80, 80))
        self.last_music.setStyleSheet("QPushButton {\"\n"
"              \"background-color: green;\"\n"
"                              \"font: bold 20px;\"    \n"
"                              \"border-width: 1px;\"    \n"
"                              \"border-radius: 40px;\" \n"
"                              \"color: white;\"      \n"
"                              }")
        self.last_music.setText("")
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap(":/put1/IMG/按钮/上首按钮.png"), QtGui.QIcon.Active, QtGui.QIcon.Off)
        self.last_music.setIcon(icon1)
        self.last_music.setIconSize(QtCore.QSize(40, 40))
        self.last_music.setObjectName("last_music")
        self.gridLayout_3.addWidget(self.last_music, 3, 2, 1, 1)
        self.jumpgif = QtWidgets.QLabel(self.groupBox_2)
        self.jumpgif.setMinimumSize(QtCore.QSize(0, 40))
        self.jumpgif.setMaximumSize(QtCore.QSize(16777215, 50))
        self.jumpgif.setSizeIncrement(QtCore.QSize(0, 0))
        self.jumpgif.setBaseSize(QtCore.QSize(0, 0))
        self.jumpgif.setFrameShape(QtWidgets.QFrame.Panel)
        self.jumpgif.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.jumpgif.setObjectName("jumpgif")
        self.gridLayout_3.addWidget(self.jumpgif, 0, 0, 1, 10)
        self.timeshow = QtWidgets.QLabel(self.groupBox_2)
        self.timeshow.setMinimumSize(QtCore.QSize(55, 0))
        self.timeshow.setMaximumSize(QtCore.QSize(60, 60))
        self.timeshow.setObjectName("timeshow")
        self.gridLayout_3.addWidget(self.timeshow, 2, 8, 1, 1)
        self.play_stop_music = QtWidgets.QPushButton(self.groupBox_2)
        self.play_stop_music.setMinimumSize(QtCore.QSize(0, 30))
        self.play_stop_music.setMaximumSize(QtCore.QSize(40, 40))
        self.play_stop_music.setStyleSheet("")
        self.play_stop_music.setText("")
        icon2 = QtGui.QIcon()
        icon2.addPixmap(QtGui.QPixmap(":/put1/IMG/按钮/播放按钮.png"), QtGui.QIcon.Active, QtGui.QIcon.On)
        self.play_stop_music.setIcon(icon2)
        self.play_stop_music.setIconSize(QtCore.QSize(40, 40))
        self.play_stop_music.setCheckable(False)
        self.play_stop_music.setChecked(False)
        self.play_stop_music.setAutoRepeat(False)
        self.play_stop_music.setAutoExclusive(False)
        self.play_stop_music.setObjectName("play_stop_music")
        self.gridLayout_3.addWidget(self.play_stop_music, 3, 1, 1, 1)
        self.horizontalSlider = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setTickPosition(QtWidgets.QSlider.NoTicks)
        self.horizontalSlider.setObjectName("horizontalSlider")
        self.gridLayout_3.addWidget(self.horizontalSlider, 2, 0, 1, 8)
        self.label_3 = QtWidgets.QLabel(self.groupBox_2)
        self.label_3.setStyleSheet("image: url(:/put1/IMG/独家.png);")
        self.label_3.setText("")
        self.label_3.setObjectName("label_3")
        self.gridLayout_3.addWidget(self.label_3, 2, 9, 2, 1)
        self.soundvalue = QtWidgets.QLabel(self.groupBox_2)
        self.soundvalue.setMaximumSize(QtCore.QSize(50, 50))
        self.soundvalue.setObjectName("soundvalue")
        self.gridLayout_3.addWidget(self.soundvalue, 3, 8, 1, 1)
        self.verticalSlider = QtWidgets.QSlider(self.groupBox_2)
        self.verticalSlider.setStyleSheet("")
        self.verticalSlider.setMaximum(100)
        self.verticalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.verticalSlider.setObjectName("verticalSlider")
        self.gridLayout_3.addWidget(self.verticalSlider, 3, 6, 1, 2)
        self.comboBox = QtWidgets.QComboBox(self.groupBox_2)
        self.comboBox.setMinimumSize(QtCore.QSize(0, 40))
        self.comboBox.setMaximumSize(QtCore.QSize(100, 16777215))
        self.comboBox.setObjectName("comboBox")
        icon3 = QtGui.QIcon()
        icon3.addPixmap(QtGui.QPixmap(":/put1/IMG/next.png"), QtGui.QIcon.Active, QtGui.QIcon.On)
        self.comboBox.addItem(icon3, "")
        icon4 = QtGui.QIcon()
        icon4.addPixmap(QtGui.QPixmap(":/put1/IMG/循环.jpg"), QtGui.QIcon.Active, QtGui.QIcon.On)
        self.comboBox.addItem(icon4, "")
        self.gridLayout_3.addWidget(self.comboBox, 3, 3, 1, 2)
        self.showgdance0 = QtWidgets.QLabel(self.groupBox_2)
        self.showgdance0.setMinimumSize(QtCore.QSize(132, 0))
        self.showgdance0.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.showgdance0.setStyleSheet("background-color: rgb(208, 208, 208);")
        self.showgdance0.setFrameShape(QtWidgets.QFrame.WinPanel)
        self.showgdance0.setFrameShadow(QtWidgets.QFrame.Raised)
        self.showgdance0.setObjectName("showgdance0")
        self.gridLayout_3.addWidget(self.showgdance0, 1, 0, 1, 3)
        self.showgdance1 = QtWidgets.QLabel(self.groupBox_2)
        self.showgdance1.setMinimumSize(QtCore.QSize(132, 0))
        self.showgdance1.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.showgdance1.setStyleSheet("background-color: rgb(208, 208, 208);")
        self.showgdance1.setFrameShape(QtWidgets.QFrame.WinPanel)
        self.showgdance1.setFrameShadow(QtWidgets.QFrame.Raised)
        self.showgdance1.setObjectName("showgdance1")
        self.gridLayout_3.addWidget(self.showgdance1, 1, 8, 1, 2)
        self.label = QtWidgets.QLabel(self.groupBox_2)
        self.label.setEnabled(True)
        self.label.setFrameShape(QtWidgets.QFrame.Panel)
        self.label.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.label.setObjectName("label")
        self.gridLayout_3.addWidget(self.label, 3, 5, 1, 1)
        self.scrollArea = QtWidgets.QScrollArea(self.groupBox_2)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 183, 343))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.gridLayout = QtWidgets.QGridLayout(self.scrollAreaWidgetContents)
        self.gridLayout.setObjectName("gridLayout")
        self.textEdit = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
        self.textEdit.setMaximumSize(QtCore.QSize(16777215, 50))
        self.textEdit.setStyleSheet("background-color: rgba(255, 255, 255, 0.1);")
        self.textEdit.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.textEdit.setObjectName("textEdit")
        self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1)
        self.textEdit_2 = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
        self.textEdit_2.setMaximumSize(QtCore.QSize(16777215, 50))
        self.textEdit_2.setStyleSheet("background-color: rgba(255, 255, 255, 0.1);")
        self.textEdit_2.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.textEdit_2.setObjectName("textEdit_2")
        self.gridLayout.addWidget(self.textEdit_2, 1, 0, 1, 1)
        self.textEdit_3 = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
        self.textEdit_3.setMaximumSize(QtCore.QSize(16777215, 50))
        self.textEdit_3.setStyleSheet("background-color: rgba(255, 255, 255, 0.1);")
        self.textEdit_3.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.textEdit_3.setObjectName("textEdit_3")
        self.gridLayout.addWidget(self.textEdit_3, 2, 0, 1, 1)
        self.textEdit_4 = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
        self.textEdit_4.setMaximumSize(QtCore.QSize(16777215, 50))
        self.textEdit_4.setStyleSheet("background-color: rgba(255, 255, 255, 0.1);")
        self.textEdit_4.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.textEdit_4.setObjectName("textEdit_4")
        self.gridLayout.addWidget(self.textEdit_4, 3, 0, 1, 1)
        self.textEdit_5 = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
        self.textEdit_5.setMaximumSize(QtCore.QSize(16777215, 50))
        self.textEdit_5.setStyleSheet("background-color: rgba(255, 255, 255, 0.1);")
        self.textEdit_5.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.textEdit_5.setObjectName("textEdit_5")
        self.gridLayout.addWidget(self.textEdit_5, 4, 0, 1, 1)
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.gridLayout_3.addWidget(self.scrollArea, 1, 3, 1, 5)
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.groupBox_2)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 685, 23))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.groupBox.setTitle(_translate("MainWindow", "曲目"))
        self.pushButton.setText(_translate("MainWindow", "上级"))
        self.device_ret.setText(_translate("MainWindow", "音频设备"))
        self.groupBox_2.setTitle(_translate("MainWindow", "播放显示"))
        self.jumpgif.setText(_translate("MainWindow", "<html><head/><body><p align=\"center\">展示GIF</p></body></html>"))
        self.timeshow.setText(_translate("MainWindow", "<html><head/><body><p>0:0/0:0</p></body></html>"))
        self.soundvalue.setText(_translate("MainWindow", "<html><head/><body><p>0</p></body></html>"))
        self.comboBox.setItemText(0, _translate("MainWindow", "单曲循环"))
        self.comboBox.setItemText(1, _translate("MainWindow", "列表循环"))
        self.showgdance0.setText(_translate("MainWindow", "<html><head/><body><p align=\"center\">GIF跳动</p></body></html>"))
        self.showgdance1.setText(_translate("MainWindow", "<html><head/><body><p align=\"center\">GIF跳动</p></body></html>"))
        self.label.setText(_translate("MainWindow", "音量设置:"))
        self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
        self.textEdit_2.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
        self.textEdit_3.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
        self.textEdit_4.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
        self.textEdit_5.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
        self.menu.setTitle(_translate("MainWindow", "文件"))
from UI_files import putton_rc

三:界面设计完成,编写运行程序

(1)主程序文件:main.py

# -*- coding: UTF-8 -*-
import time
import os,logging
from UI_files.Ui_music import Ui_MainWindow
import sys
from PyQt5.QtGui import QIcon,QDesktopServices,QMovie # 用于添加图标
from PyQt5.QtWidgets import QMessageBox, QAction
from PyQt5.QtWidgets import QApplication,QMainWindow
from PyQt5.QtCore import pyqtSlot,QCoreApplication,QUrl,Qt
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import traceback
from qtthread import RunThread


class Music_play(QMainWindow, Ui_MainWindow): 
    def __init__(self):
        super().__init__() # 使用超类,继承父类的属性及方法
        self.setupUi(self) # 构造窗体界面
        self.setWindowIcon(QIcon("./IMG/icon/icon.jpg"))
        self.setWindowTitle("自用音乐播放器V1.0 ") # 设置窗体主体
        self.intUI()

    # 初始化操作
    def intUI(self):
        self.my_logger = self.save_log()
        self.piaymusicret = False
        self.devices_ret = True
        self.thread_1 = None
        self.playmusic()
        self.set_vo_init()
        self.verticalSlider.valueChanged.connect(self.sl_value)
        self.horizontalSlider.valueChanged.connect(self.set_music_current_time)
        self.init_dongzuo()
        self.init_dance()
        self.create_folder()
        self.get_musicfiles()
        self.listWidget.itemDoubleClicked.connect(self.openmusicfiles) #绑定点击事件
        self.menu_add()
        
     # 添加打开本地文件夹按钮
    def menu_add(self):
        add_opeen= QAction("打开",self)
        add_opeen.setShortcut('Ctrl+F')
        add_opeen.triggered.connect(self.open_local_file)
        self.menu.addAction(add_opeen)
        add_opeens= QAction("重启工具",self)
        add_opeens.setShortcut('Ctrl+S')
        add_opeens.triggered.connect(self.restartApp)
        self.menu.addAction(add_opeens)

        self.textEdit.setDisabled(True)
        self.textEdit_2.setDisabled(True)
        self.textEdit_3.setDisabled(True)
        self.textEdit_4.setDisabled(True)
        self.textEdit_5.setDisabled(True)

    # 打开本地文件夹
    def open_local_file(self):
        path = os.getcwd()
        QDesktopServices.openUrl(QUrl.fromLocalFile(path))

    # 重启软件
    def restartApp(self):
        python = sys.executable
        os.execl(python, python, *sys.argv)

    # 异常处理函数
    def yichangchuli(func=None):
        def deco(self,*args, **kwargs): 
            # print(func.__name__) #获取方法名称
            try:
                res = func(self,*args, **kwargs)
                return res 
            except Exception as error:
                error = traceback.format_exc()
                print("错误异常:",error)
                self.my_logger.debug(str(error))
                if "_ctypes.COMError" in error:
                    self.close_button()
                    self.devices_ret = False
        return deco


    # 日志管理
    def save_log(self):
        # 1.创建一个logger(日志记录器)对象;
        my_logger = logging.Logger("first_logger")
        # 2.定义handler(日志处理器),决定把日志发到哪里;
        my_handler = logging.FileHandler('日志.log',encoding='utf-8')
        # 3.设置日志级别(level)和输出格式Formatters(日志格式器);
        my_handler.setLevel(logging.DEBUG)
        my_format = logging.Formatter("时间:%(asctime)s 函数名:%(funcName)s 日志信息:%(message)s 行号:%(lineno)d")
        # 把handler添加到对应的logger中去。
        my_handler.setFormatter(my_format)
        my_logger.addHandler(my_handler)

        # 使用:
        my_logger.info("程序已启动...")
        return my_logger

    # 日志记录
    def save_logshuju(self,value):
        self.my_logger.debug(value)
        
    def close_button(self):
        self.play_stop_music.setEnabled(False)
        self.next_music.setEnabled(False)
        self.last_music.setEnabled(False)
        self.device_ret.setStyleSheet("background-color: red")
        self.device_ret.setText("音频打开失败")

    # 横幅
    def init_dongzuo(self):
        path = "./IMG/横幅GIF1.gif"
        movie = QMovie(path)
        self.jumpgif.setMovie(movie)
        self.jumpgif.setScaledContents(True)
        movie.start()
    
    # GFI 跳动1
    def init_dance(self):
        path = "./IMG/dance0.gif"
        movie = QMovie(path)
        self.showgdance0.setMovie(movie)
        self.showgdance0.setScaledContents(True)
        movie.start()
        self.next_music.setEnabled(False)
        self.last_music.setEnabled(False)
        self.init_dances()
    
      # GFI 跳动2
    def init_dances(self):
        path = "./IMG/dance0.gif"
        movie = QMovie(path)
        self.showgdance1.setMovie(movie)
        self.showgdance1.setScaledContents(True)
        movie.start()
       
    # 如若没有,音乐文件自动创建
    def create_folder(self):
        paths = ["./音乐/音频文件","./音乐/歌词文件"]
        for p in paths:
            if os.path.isdir(p):
                pass
            else:
                os.mkdir(p)

    # 获取音频文件,并显示至界面
    def get_musicfiles(self):
        self.foder = None
        self.listWidget.clear()
        path = "./音乐"
        musicfiles = os.listdir(path)
        for file in musicfiles:
            self.listWidget.addItem(file)
    

    # 打开文件夹,列出音乐文件
    def openmusicfiles(self):
        # 判断是否为文件夹
        selected_item = self.listWidget.currentItem()
        item_text = selected_item.text()
        music_name = ["mp3"]
        try:
            path = os.getcwd() + "/音乐/" + item_text
            musicfiles = os.listdir(path)
        except FileNotFoundError as error:
            if self.devices_ret == False:
                return
            if self.thread_1 != None:
                # 判断线程是否还在运行
                if self.thread_1.isRunning():
                    print("线程正在运行")
                    self.thread_1.set_ret()
                    self.thread_1.quit()
                    time.sleep(0.3)
            paths = self.foder +"/{}".format(item_text)
            self.thread_1 = RunThread(parent="music_bofang",msg=[paths])
            self.thread_1.trigger.connect(self.send_information)
            self.thread_1.start()

            self.playmusic()
            self.groupBox_2.setTitle("播放显示:{}".format(item_text))
            return item_text
       
        self.listWidget.clear()
        for file in musicfiles:
            for name in music_name:
                self.foder = path
                if name in file:
                    self.listWidget.addItem(file)
        if self.groupBox_2.title() == "播放显示":
            # 设置第当前选择的项0
            current_item = self.listWidget.item(0)
            self.listWidget.setCurrentItem(current_item)
        else:
            shuju = str(self.groupBox_2.title()).split(":")
            for i in range(self.listWidget.count()):
                item = self.listWidget.item(i)
                text = item.text()
                if text == shuju[1]:
                    current_item = self.listWidget.item(i)
                    self.listWidget.setCurrentItem(current_item)

    @pyqtSlot()
    def on_pushButton_clicked(self):
        if self.thread_1 != None:
            # 判断线程是否还在运行
            if self.thread_1.isRunning():
                print("线程正在运行")
                # 后两项分别为按钮(以|隔开,共有7种按钮类型,见示例后)、默认按钮(省略则默认为第一个按钮)
                reply = QMessageBox.question(self, "音乐", "是否停止播放音乐,返回上级目录?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
                if reply == 16384:
                    self.thread_1.set_ret()
                    self.thread_1.quit()
                    time.sleep(0.5)
                    self.get_musicfiles()
                    self.thread_1 = None
        else:
            self.get_musicfiles()

    # 获取当前电脑的音量值,并设置
    @yichangchuli
    def set_vo_init(self):
        self.play_stop_music.setEnabled(False)
        # 获取自己的音频设备及其参数
        devices = AudioUtilities.GetSpeakers()
        interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
        volume = cast(interface, POINTER(IAudioEndpointVolume))

        # 获取音量范围,我的电脑经测试是(-65.25, 0.0, 0.03125),第一个代表最小值,第二个代表最大值,第三个是增量。
        vol_range = volume.GetVolumeRange()
        print(vol_range)
 
        # 获取当前的音量值
        vol_now = volume.GetMasterVolumeLevel()
        print("获取音量数值:",int(vol_now))

        value = self.vol_tansfer(x=int(vol_now),chang="get")
        _translate = QCoreApplication.translate
        self.soundvalue.setText(_translate("MainWindow", "<html><head/><body><p align=\"center\">{}</p></body></html>".format(value)))
        self.verticalSlider.setValue(value)
        self.device_ret.setStyleSheet("background-color: green")
        self.device_ret.setText("音频打开成功")
        self.devices_ret = True


    # 播放音乐
    def playmusic(self):
        self.piaymusicret = True
        self.play_stop_music.setIcon(QIcon('./IMG/按钮/播放按钮1.png'))
    

    @pyqtSlot()
    def on_device_ret_clicked(self):
        if self.device_ret.text() == "音频打开失败":
            self.set_vo_init()

    # 播放暂停按钮
    @pyqtSlot()
    def on_play_stop_music_clicked(self):
        if self.piaymusicret == True:
            self.play_stop_music.setIcon(QIcon('./IMG/按钮/暂停按钮.png'))
            self.piaymusicret = None
            self.thread_1.music_stop()
        elif self.piaymusicret == None:
            self.play_stop_music.setIcon(QIcon('./IMG/按钮/播放按钮1.png'))
            self.piaymusicret = True
            self.thread_1.music_bofangs()
    
    # 设置音量
    def sl_value(self):
        _translate = QCoreApplication.translate
        value = self.verticalSlider.value()
        self.soundvalue.setText(_translate("MainWindow", "<html><head/><body><p align=\"center\">{}</p></body></html>".format(value)))
        self.set_volume(value)

    # 设置音乐时间
    def set_music_current_time(self):
        pass

    @pyqtSlot()
    def on_last_music_pressed(self):
        self.last_music.setIcon(QIcon('./IMG/按钮/上首按钮1.png'))
    
    # 切换上一首歌
    @pyqtSlot()
    def on_last_music_released(self):
        self.last_music.setIcon(QIcon('./IMG/按钮/上首按钮.png'))
        # 获取所有数据的数量
        all_suoyin = self.listWidget.count()
        print(all_suoyin)
     
        # 获取当前选中的所有项
        selected_items = self.listWidget.selectedItems()

        # 获取当前选中项的索引
        selected_indexes = [self.listWidget.row(item) for item in selected_items]

        print(selected_indexes[0])  # 输出选中项的索引

        if selected_indexes[0]-1 >= 0:
            # 设置第当前选择的项
            current_item = self.listWidget.item(selected_indexes[0]-1)
            self.listWidget.setCurrentItem(current_item)
            # 设置选中项的背景样式
            self.listWidget.setStyleSheet("QListWidget::item:selected { background-color: rgb(0, 255, 127); }")
            # 判断线程是否还在运行
            if self.thread_1.isRunning():
                print("线程正在运行")
                self.thread_1.set_ret()
                self.thread_1.quit()
            else:
                print("线程已停止")
            self.openmusicfiles()
        
    @pyqtSlot()
    def on_next_music_pressed(self):
        self.next_music.setIcon(QIcon('./IMG/按钮/下首按钮1.png'))
    
    # 切换下一首歌
    @pyqtSlot()
    def on_next_music_released(self):
        self.next_music.setEnabled(False)
        self.next_music.setIcon(QIcon('./IMG/按钮/下首按钮.png'))
        # 获取所有数据的数量
        all_suoyin = self.listWidget.count()
        print(all_suoyin)
     
        # 获取当前选中的所有项
        selected_items = self.listWidget.selectedItems()

        # 获取当前选中项的索引
        selected_indexes = [self.listWidget.row(item) for item in selected_items]

        print(selected_indexes[0])  # 输出选中项的索引

        if selected_indexes[0]+1 <= all_suoyin-1:
            # 设置第当前选择的项
            current_item = self.listWidget.item(selected_indexes[0]+1)
            self.listWidget.setCurrentItem(current_item)
            # 设置选中项的背景样式
            self.listWidget.setStyleSheet("QListWidget::item:selected { background-color: rgb(0, 82, 245); }")
            # 判断线程是否还在运行
            if self.thread_1.isRunning():
                print("线程正在运行")
                self.thread_1.set_ret()
                self.thread_1.quit()
            else:
                print("线程已停止")
            time.sleep(0.2)
            self.openmusicfiles()

    # 列表循环切歌
    @pyqtSlot()
    def listcutmusic(self):
        self.next_music.setIcon(QIcon('./IMG/按钮/下首按钮.png'))
        # 获取所有数据的数量
        all_suoyin = self.listWidget.count()
        print("所有数量:",all_suoyin)
     
        # 获取当前选中的所有项
        selected_items = self.listWidget.selectedItems()

        # 获取当前选中项的索引
        selected_indexes = [self.listWidget.row(item) for item in selected_items]

        print(selected_indexes[0])  # 输出选中项的索引

        if selected_indexes[0]+1 <= all_suoyin-1:
            # 设置第当前选择的项
            current_item = self.listWidget.item(selected_indexes[0]+1)
            self.listWidget.setCurrentItem(current_item)
            # 设置选中项的背景样式
            self.listWidget.setStyleSheet("QListWidget::item:selected { background-color: rgb(0, 82, 245); }")
            text = self.openmusicfiles()
        elif  selected_indexes[0]+1 > all_suoyin-1:
            # 设置第当前选择的项
            current_item = self.listWidget.item(0)
            self.listWidget.setCurrentItem(current_item)
            # 设置选中项的背景样式
            self.listWidget.setStyleSheet("QListWidget::item:selected { background-color: rgb(0, 82, 245); }")
            text = self.openmusicfiles()
        return text

    # 设置音量值
    @yichangchuli
    def set_volume(self,volume=None):
        # 调用Windows API函数
        # 获取自己的音频设备及其参数
        devices = AudioUtilities.GetSpeakers()
        interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
        volumes = cast(interface, POINTER(IAudioEndpointVolume))
        #设置声音大小
        volumes.SetMasterVolumeLevel(self.vol_tansfer(volume), None)

    # 音量值转换
    def vol_tansfer(self,x,chang=None):
        dicts = {0: -63.05, 1: -56.99, 2: -51.67, 3: -47.74, 4: -44.62, 5: -41.03, 6: -39.82, 7: -37.89, 8: -36.17,
                9: -34.63, 10: -33.24,
                11: -31.96, 12: -30.78, 13: -29.68, 14: -28.66, 15: -27.7, 16: -26.8, 17: -25.95, 18: -25.15, 19: -24.38,
                20: -23.65,
                21: -22.96, 22: -22.3, 23: -21.66, 24: -21.05, 25: -20.46, 26: -19.9, 27: -19.35, 28: -18.82, 29: -18.32,
                30: -17.82,
                31: -17.35, 32: -16.88, 33: -16.44, 34: -16.0, 35: -15.58, 36: -15.16, 37: -14.76, 38: -14.37, 39: -13.99,
                40: -13.62,
                41: -13.26, 42: -12.9, 43: -12.56, 44: -12.22, 45: -11.89, 46: -11.56, 47: -11.24, 48: -10.93, 49: -10.63,
                50: -10.33,
                51: -10.04, 52: -9.75, 53: -9.47, 54: -9.19, 55: -8.92, 56: -8.65, 57: -8.39, 58: -8.13, 59: -7.88,
                60: -7.63,
                61: -7.38, 62: -7.14, 63: -6.9, 64: -6.67, 65: -6.44, 66: -6.21, 67: -5.99, 68: -5.76, 69: -5.55, 70: -5.33,
                71: -5.12, 72: -4.91, 73: -4.71, 74: -4.5, 75: -4.3, 76: -4.11, 77: -3.91, 78: -3.72, 79: -3.53, 80: -3.34,
                81: -3.15, 82: -2.97, 83: -2.79, 84: -2.61, 85: -2.43, 86: -2.26, 87: -2.09, 88: -1.91, 89: -1.75,
                90: -1.58,
                91: -1.41, 92: -1.25, 93: -1.09, 94: -0.93, 95: -0.77, 96: -0.61, 97: -0.46, 98: -0.3, 99: -0.15, 100: 0.0}
        if chang == None:
            return dicts[x]
        elif chang == "get":
            for value,shuju in dicts.items():
                if str(x) in str(shuju):
                    print(value)
                    return value
    
    def get_time(self):
        shijian = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        return shijian

    # 接收信息
    def send_information(self,text=[]):
        #接收信息
        time_now = self.get_time()
        if text[0] == "musicplay_end":
            if self.comboBox.currentText() == "单曲循环":
                if self.piaymusicret == True:
                    item_text = self.openmusicfiles()
                    self.my_logger.info("单曲循环:"+ item_text)
            elif self.comboBox.currentText() == "列表循环":
                text = self.listcutmusic()
                self.my_logger.info("当前播放歌曲:"+ text)
        elif text[0] == "error_save":
            self.my_logger.debug(text[1])
        elif text[0] == "music_time":
            self.timeshow.setText(text[1])
        elif text[0] == "musicplay_time":
            # 设置音乐时长大小
            self.horizontalSlider.setMaximum(int(text[1]))  # 设置最大值为10
        elif text[0] == "music_time_slider":
            self.horizontalSlider.setValue(int(text[1]))
        elif text[0] == "pustton_huifu":
            self.play_stop_music.setEnabled(True)
            self.next_music.setEnabled(True)
            self.last_music.setEnabled(True)
        elif text[0] == "show_gechi":
            if text[1][0] == 0:
                self.textEdit.setText(text[1][1])
                self.textEdit.setAlignment(Qt.AlignCenter)   # 设置文本居中对齐
            elif text[1][0] == 1:
                self.textEdit_2.setText(text[1][1])
                self.textEdit_2.setAlignment(Qt.AlignCenter)  # 设置文本居中对齐
            elif text[1][0] == 2:
                self.textEdit_3.setText(text[1][1])
                self.textEdit_3.setAlignment(Qt.AlignCenter)  # 设置文本居中对齐
            elif text[1][0] == 3:
                self.textEdit_4.setText(text[1][1])
                self.textEdit_4.setAlignment(Qt.AlignCenter)  # 设置文本居中对齐
            elif text[1][0] == 4:
                self.textEdit_5.setText('<font color=\"#0000FF\">{}</font>'.format(text[1][1]))
                self.textEdit_5.setAlignment(Qt.AlignCenter)  # 设置文本居中对齐
        elif text[0] == "nomusicfile":
            self.textEdit.setText(text[1])
            self.textEdit.setAlignment(Qt.AlignCenter)  # 设置文本居中对齐
        elif text[0] == "clear_musicfile":
            self.textEdit.setText("")
            self.textEdit_2.setText("")
            self.textEdit_3.setText("")
            self.textEdit_4.setText("")
            self.textEdit_5.setText("")

    def closeEvent(self, event):
        """
        重写closeEvent方法,实现dialog窗体关闭时执行一些代码
        :param event: close()触发的事件
        :return: None
        """
        reply = QMessageBox.question(self,
                                               '本程序',
                                               "是否要退出程序?",
                                               QMessageBox.Yes | QMessageBox.No,
                                               QMessageBox.Yes)
        if reply == QMessageBox.Yes:

            if self.thread_1 != None:
                # 判断线程是否还在运行
                if self.thread_1.isRunning():
                    print("线程正在运行")
                    self.thread_1.set_ret()
                    self.thread_1.quit()
                    self.thread_1.wait()
                    
                else:
                    print("线程已停止")
            event.accept()
            
        else:
            event.ignore()



if __name__ == "__main__":
    app = QApplication(sys.argv)
    # 设置应用程序的风格
    app.setStyle('Fusion')
    w = Music_play()
    w.show()
    sys.exit(app.exec_())

(2)业务逻辑程序文件(处理耗时过长的程序):qtthread.py

from PyQt5.QtCore import pyqtSignal,QThread
import traceback
import os
import time
from pygame import mixer
from mutagen.mp3 import MP3

#业务线程
class RunThread(QThread):
    # 通过类成员对象定义信号对象
    # _signal = pyqtSignal(str)

    trigger = pyqtSignal(list)

    def __init__(self, parent=None,msg=None):
      super(RunThread, self).__init__()
      self.parent = parent
      self.msg = msg

    # def __del__(self): #等待
    #   self.wait()    
    
    # 异常处理函数
    def yichangchuli(func=None):
        def deco(self,*args, **kwargs): 
            # print(func.__name__) #获取方法名称
            try:
                res = func(self,*args, **kwargs)
                return res 
            except Exception as error:
                error = traceback.format_exc()
                print("错误异常:",error)
                self.send_emit(change="error_save",result="{}".format(error))
        return deco
    
    '''处理业务逻辑'''
    @yichangchuli
    def run(self):
        #识别业务命令,在进行执行
        if self.parent == "music_bofang":
            self.save_gechi = []
            self.music_bofang()
            
    def music_bofang(self):
        paths = self.msg[0]
        print(paths)
        self.mixer = mixer
        self.mixer.init()
        self.mixer.music.load(paths)
        # 获取音频时长
        audio = MP3(paths)
        duration = audio.info.length
        # 输出音乐时长
        print("音乐时长:", duration)
        self.send_times(du=int(duration))
        
        shijian = self.jisuan_time(du=duration)

        # 设置音乐播放完成事件
        self.mixer.music.set_endevent()
        self.mixer.music.play()
        self.send_emit(change="pustton_huifu",result="true")

        time.sleep(0.5)
        self.pos_get(du=shijian)
        
        # self.jianting()

    def pos_get(self,du):
        # 处理歌词和时间
        liebiaotime = self.count_func()
        if liebiaotime != None:
            self.gechi = liebiaotime[1]
            print("歌词:",liebiaotime[1])
            # 清除显示的文件
            self.send_emit(change="clear_musicfile",result="")
        else:
            self.send_emit(change="clear_musicfile",result="")
            self.send_emit(change="nomusicfile",result="无对应歌词文件")
        shuju =  str(du).split(":")
        shuju = int(shuju[0])*60+ int(shuju[1])
        print("总时间:",shuju)
        self.ret = True
        while self.ret:
            time.sleep(1)
            if self.ret == False:
                print("线程结束!")
                self.mixer.music.stop()
                self.mixer.stop()
                break
            pos = self.mixer.music.get_pos()
            print("位置:",int(pos/1000))
            weizhi = int(pos/1000)
            if 0 < int(pos/1000) < 60:
                self.send_emit(change="music_time",result="{}-{}".format(int(pos/1000),du))
                self.send_emit(change="music_time_slider",result="{}".format(int(pos/1000)))
                if liebiaotime != None:
                    self.show_music_gechi(liebiao=liebiaotime,weizhi=weizhi)
            elif 60 <= int(pos/1000) < shuju:
                self.send_emit(change="music_time_slider",result="{}".format(int(pos/1000)))
                shujus = self.jisuan_time(du=int(pos/1000))
                self.send_emit(change="music_time",result="{}-{}".format(shujus,du))
                if liebiaotime != None:
                    self.show_music_gechi(liebiao=liebiaotime,weizhi=weizhi)
            elif weizhi >= shuju or weizhi == 0:
                print("播放结束!")
                self.ret = False
                self.mixer.stop()
                self.send_emit(change="musicplay_end",result="播放结束")

    # 对应时间的对应歌词显示
    def show_music_gechi(self,liebiao,weizhi):
        weizhi = self.chuli_weizhi(weizhi)
        index = liebiao[0].index(str(weizhi)) if (str(weizhi) in liebiao[0]) else -1     # 有则返回下标,没有返回-1
        # print('列表中元素"{}"的下标为:'.format(weizhi), index)
        if index != -1:
            self.send_gechi(index)

    # 处理歌词的时间
    def chuli_weizhi(self,shuju):
        if  0 < shuju < 10:
            shuju = "00:0{}".format(shuju)
        elif 10 <= shuju < 60:
            shuju = "00:{}".format(shuju)
        elif 60 <= shuju < 70:
            shujus = self.jisuan_time(shuju)
            shujus = shujus.split(":")
            shujus = shujus[0]+":0" +shujus[1]
            shuju = "0{}".format(shujus)
            # print("=====",shuju)
        elif 70 <= shuju: 
            shujus = self.jisuan_time(shuju)   
            shuju = "0{}".format(shujus)
        return shuju

    def send_gechi(self,index):
        shuju = self.gechi[index]
        # print("打印歌词:",shuju)
        # 保存歌词的列表,数目只能保持在5个
        self.save_gechi.append(shuju)
        if len(self.save_gechi) <= 5:
            i=0
            for gechi_shuju in self.save_gechi:
                self.send_emits(change="show_gechi",result=[i,gechi_shuju])
                i= i+1
        else:
            self.save_gechi.pop(0)
            i=0
            for gechi_shuju in self.save_gechi:
                self.send_emits(change="show_gechi",result=[i,gechi_shuju])
                i= i+1

    # 处理歌词和时间
    def count_func(self):
        filepath = str(self.msg[0]).replace("音频文件","歌词文件")
        filepath = filepath.split(".")
        filepath = filepath[0] + ".txt"
        print("歌词文件路径:",filepath)
        # 判断歌词文件是否存在
        if os.path.exists(filepath):
            #filepath = "F:/personaldata/Python资料/Python_studyltem/自制音乐播放器0103/音乐/歌词文件/姑娘别哭泣.txt"
            with open(filepath, 'r',encoding="gbk") as f:
                self.data = f.readlines()
                # print(self.data)
            # 歌词数据处理 分开时间和歌词,一一对应,列表保存数据
            liebiao1 = []
            liebiao2 = []
            for shuju in self.data:
                timesave0 = shuju.split("]")
                timesave1 = timesave0[0].replace("[","")
                # print(timesave1)
                timesave2 = timesave1.split(".")
                timesave3 = timesave2[0]
                # print(timesave3)
                # 保存时间
                liebiao1.append(timesave3)
                # 保存歌词
                liebiao2.append(timesave0[1])
            print("歌词时间:",liebiao1)
            return [liebiao1,liebiao2]
        else:
            self.send_emit(change="error_save",result="无歌词文件:".format(filepath))
            return None

    def jianting(self):
        # 监听事件
        while True: 
            ret = self.mixer.music.get_busy()
            if ret == True:
                continue
            elif ret == False:
                print('音乐播放完成')
                self.mixer.music.stop()
                self.send_emit(change="musicplay_end",result="播放结束")
                break
            else:
                shuju = self.mixer.music.get_endevent()
                print("异常错误:",shuju)

    # 计算音频时长
    def jisuan_time(self,du):
        y = 0
        for i in range(1,5):
            y = int(du) - i*60
            if 0 <= y < 60:
                shijian = str(i) +":"+"{}".format(y)
                print("转化时间:",shijian) 
                return shijian
    
    # 将计算的时间,传给主界面
    def send_times(self,du):
        self.send_emit(change="musicplay_time",result="{}".format(du))


    # 停止获取音频位置数据
    def set_ret(self):
        self.ret = False

    # 音乐停止
    def music_stop(self):
        self.mixer.music.pause()

     # 音乐停止
    def music_bofangs(self):
        self.mixer.music.unpause()


    def send_emit(self,change="info",result=""):
        self.trigger.emit([change, result])

    def send_emits(self,change="info",result=[]):
        self.trigger.emit([change, result])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山中坐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值