Oct-16-2021, 10:49 PM
Much better now. A thought occurred to me.
Why the extra exit button?
Maybe a volume slider makes more sense at this point.
Why the extra exit button?
Maybe a volume slider makes more sense at this point.
#!/usr/bin/python3 # -*- coding: utf-8 -*- from functools import partial import os import sys from PyQt5.QtCore import Qt, QUrl, QDir from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QGridLayout, \ QFrame, QGraphicsDropShadowEffect, QGraphicsView, QGraphicsScene, QLabel, \ QPushButton, QHBoxLayout, QStyle, QListWidget, QFileDialog, QSlider, QVBoxLayout from PyQt5.QtGui import QGradient, QFont, QColor, QCursor, QIcon, QPixmap from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QMediaPlaylist, \ QMediaMetaData class Window(QMainWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setWindowTitle('PyQt5 Music Player') # Create a containers btn_box = QHBoxLayout() btn_box2 = QHBoxLayout() container = QGridLayout() info_container = QGridLayout() frame = QFrame() frame.setFrameShape(QFrame.Box) frame.setFrameShadow(QFrame.Sunken) frame.setLayout(info_container) # Create some variables self.dir = f'{QDir.currentPath()}' self.url = QUrl() self.player = QMediaPlayer() self.content = QMediaContent() self.playlist = QMediaPlaylist(self.player) self.player.setPlaylist(self.playlist) # Used to changed to notify self.update that the playlist index has changed. # Will update the highlighted line in the listbox self.playlist.currentIndexChanged.connect(self.update) # Signal that the metadate has changed self.player.metaDataChanged.connect(self.meta_data) # Labels for the track information self.artist = QLabel('Artist: ') self.album_title = QLabel('Album: ') self.track_title = QLabel('Track: ') self.released = QLabel('Released: ') self.genre = QLabel('Genre: ') self.art = QLabel() # Add track information to the info container info_container.addWidget(self.artist, 0, 0, 1, 1) info_container.addWidget(self.album_title, 1, 0, 1, 1) info_container.addWidget(self.track_title, 2, 0, 1, 1) info_container.addWidget(self.released, 3, 0, 1, 1) info_container.addWidget(self.genre, 4, 0, 1, 1) info_container.addWidget(self.art, 5, 0, 1, 1) # Create the status and track labels self.status = QLabel('Status: ') self.status.setFrameShape(QFrame.Box) self.status.setFrameShadow(QFrame.Sunken) self.track = QLabel('Track: ') self.track.setFrameShape(QFrame.Box) self.track.setFrameShadow(QFrame.Sunken) # Define and create the listbox self.musiclist = QListWidget() self.musiclist.setFrameShape(QFrame.Box) self.musiclist.setFrameShadow(QFrame.Sunken) self.musiclist.setStyleSheet('background-color: snow;') # Used for track play when double clicked self.musiclist.itemDoubleClicked.connect(self._doubleclick) # Create the control buttons & button styles btn_style = '''QPushButton{background-color: skyblue;} QPushButton:hover{background-color: lightskyblue; color: dodgerblue; \ font-weight: bold;}''' # Create buttons for getting audio files and clearing playlist file_btn = QPushButton('Get Audio') file_btn.setIcon(self.style().standardIcon(QStyle.SP_DirOpenIcon)) file_btn.released.connect(self._files) file_btn.setCursor(Qt.PointingHandCursor) file_btn.setStyleSheet(btn_style) file_btn.setMaximumWidth(100) clear_btn = QPushButton('Clear List') clear_btn.setIcon(self.style().standardIcon(QStyle.SP_TrashIcon)) clear_btn.released.connect(self._clear) clear_btn.setCursor(Qt.PointingHandCursor) clear_btn.setStyleSheet(btn_style) clear_btn.setMaximumWidth(100) # Create & style the control buttons self.play_btn = QPushButton('Play') self.play_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.play_btn.released.connect(self._state) self.play_btn.setCursor(Qt.PointingHandCursor) self.play_btn.setStyleSheet(btn_style) self.prev_btn = QPushButton('Prev') self.prev_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipBackward)) self.prev_btn.released.connect(self._prev) self.prev_btn.setCursor(Qt.PointingHandCursor) self.prev_btn.setStyleSheet(btn_style) self.next_btn = QPushButton('Next') self.next_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipForward)) self.next_btn.released.connect(self._next) self.next_btn.setCursor(Qt.PointingHandCursor) self.next_btn.setStyleSheet(btn_style) self.stop_btn = QPushButton('Stop') self.stop_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stop_btn.released.connect(self._stop) self.stop_btn.setCursor(Qt.PointingHandCursor) self.stop_btn.setStyleSheet(btn_style) self.vol_slider = QSlider(orientation=1) self.vol_slider.setFixedWidth(80) self.vol_slider.setRange(0, 100) self.vol_slider.valueChanged.connect(self.set_volume) self.vol_slider.setValue(75) self.vol_slider.setStyleSheet("""QSlider::groove:horizontal { border: 1px solid #999999; height: 8px; background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #686da0, stop:1 #c4c4c4); margin: 2px 0; } QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #729fcf, stop:1 #3465a4); border: 1px solid #5c5c5c; width: 18px; margin: -2px 0; border-radius: 3px;}""") self.exit_btn = QPushButton('Exit') self.exit_btn.released.connect(sys.exit) self.exit_btn.setCursor(Qt.PointingHandCursor) self.exit_btn.setStyleSheet('QPushButton{background-color: firebrick;} \ QPushButton:hover{background-color: red; color: white; \ font-weight: bold;}') # Add the buttons to layout btn_box.addWidget(file_btn) btn_box.addWidget(clear_btn) btn_box2.addWidget(self.play_btn) btn_box2.addWidget(self.prev_btn) btn_box2.addWidget(self.next_btn) btn_box2.addWidget(self.stop_btn) btn_box2.addWidget(self.vol_slider) # Add layouts to container layout container.addWidget(self._header_footer(100, 100, 40, 'PyQt5 Music Player'), 0, 0, 1, 3) container.addWidget(self.status, 1, 0, 1, 1) container.addWidget(self.track, 1, 1, 1, 1) container.addLayout(btn_box, 1, 2, 1, 1) container.addWidget(frame, 2, 0, 2, 1) container.addWidget(self.musiclist, 2, 1, 1, 2) container.addLayout(btn_box2, 3, 1, 1, 2) container.addWidget(self._header_footer(40, 40, 10, 'my-python.org - 10/16/2021'), 4, 0, 1, 3) # Create the widget and add the button box layout widget = QWidget() widget.setLayout(container) self.setCentralWidget(widget) def set_volume(self): self.player.setVolume(self.vol_slider.value()) # Get music metadata def meta_data(self): if self.player.isMetaDataAvailable(): self.artist.setText(f'Artist: {self.player.metaData(QMediaMetaData.AlbumArtist)}') self.album_title.setText(f'Album: {self.player.metaData(QMediaMetaData.AlbumTitle)}') self.track_title.setText(f'Track: {self.player.metaData(QMediaMetaData.Title)}') self.released.setText(f'Released: {self.player.metaData(QMediaMetaData.Year)}') self.genre.setText(f'Genre: {self.player.metaData(QMediaMetaData.Genre)}') self.track.setText(f'Track: {self.player.metaData(QMediaMetaData.Title)}') pixmap = QPixmap(self.player.metaData(QMediaMetaData.CoverArtImage)) pixmap = pixmap.scaled(int(pixmap.width()/3), int(pixmap.height()/3)) self.art.setPixmap(pixmap) # Create the header def _header_footer(self, minheight, maxheight, fontsize, text): shadow = QGraphicsDropShadowEffect() shadow.setBlurRadius(3) shadow.setOffset(3, 3) scene = QGraphicsScene() view = QGraphicsView() view.setMinimumSize(800, minheight) view.setMaximumHeight(maxheight) view.setScene(scene) gradient = QGradient(QGradient.RichMetal) scene.setBackgroundBrush(gradient) font = QFont('comic sans ms', fontsize, QFont.Bold) text = scene.addText(text) text.setDefaultTextColor(QColor(250,250,250)) text.setFont(font) text.setGraphicsEffect(shadow) return view # Method for double clicking a track and play def _doubleclick(self): self.playlist.setCurrentIndex(self.musiclist.currentRow()) self.player.play() # Method for clearing the playlist and musiclist def _clear(self): self.player.stop() self.musiclist.clear() self.playlist.clear() self.play_btn.setText('Play') self.status.setText('Status: ') self.track.setText('Track: ') self.artist.setText('Artist: ') self.album_title.setText('Album: ') self.track_title.setText('Track: ') self.released.setText('Released: ') self.genre.setText('Genre: ') pixmap = QPixmap() self.art.setPixmap(pixmap) # Method for adding tracks to the playlist and musiclist def _files(self): files = QFileDialog.getOpenFileNames(None, 'Get Audio Files', filter='Audio Files (*.mp3 *.ogg *.wav)') for file in files[0]: self.playlist.addMedia(QMediaContent(self.url.fromLocalFile(file))) file = file.split('/') self.musiclist.addItem(f'{file[-1][:-4]}') self.musiclist.setCurrentRow(0) self.playlist.setCurrentIndex(0) # Methods for the control buttons def _prev(self): if self.playlist.previousIndex() == -1: self.playlist.setCurrentIndex(self.playlist.mediaCount()-1) else: self.playlist.previous() def _next(self): self.playlist.next() if self.playlist.currentIndex() == -1: self.playlist.setCurrentIndex(0) self.player.play() def _stop(self): self.player.stop() self.play_btn.setText('Play') self.playlist.setCurrentIndex(0) self.musiclist.setCurrentRow(0) self.status.setText('Status: Now Stopped') def _state(self): if self.playlist.mediaCount() > 0: if self.player.state() != QMediaPlayer.PlayingState: self.play_btn.setText('Pause') self.status.setText('Status: Now Playing') self.player.setVolume(self.vol_slider.value()) self.player.play() else: self.play_btn.setText('Play') self.player.pause() self.status.setText('Status: Now Paused') else: pass # Method for updating the listbox when the playlist updates def update(self): self.musiclist.setCurrentRow(self.playlist.currentIndex()) if self.playlist.currentIndex() < 0: self.musiclist.setCurrentRow(0) self.playlist.setCurrentIndex(0) def main(): app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec()) if __name__ == '__main__': main()