因此,最近我正尝试使用PyQt5,pygame和mutagen制作音频播放器。该程序运行正常。但是当我播放歌曲并尝试退出该程序时,该程序停止响应,并且歌曲继续播放。但这不会在歌曲不播放时发生,然后可以正常工作。
以下是代码:
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QSlider
from PyQt5.QtGui import QColor
from PyQt5.QtCore import Qt
import sys
import pygame as pg
from mutagen.mp3 import MP3
import os
import threading
pg.init()
#33206
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(425, 65, 400, 190)
self.setWindowIcon(QtGui.QIcon("icon"))
self.setWindowTitle("MultiMedia Player")
# MenuBar
file = QtWidgets.QAction("&Open Mp3", self)
file.setShortcut("Ctrl + O")
file.triggered.connect(self.open_mp3)
# Quit
quit = QtWidgets.QAction("&Quit", self)
quit.setShortcut("Q")
quit.triggered.connect(self.close_app)
# Add Items
items = QtWidgets.QAction("&Add Items", self)
items.setShortcut("Ctrl + P")
mainmenu = self.menuBar()
filemenu = mainmenu.addMenu("&Open")
filemenu.addAction(file)
add_items = mainmenu.addMenu("&Add Items")
add_items.addAction(items)
filemenu.addAction(quit)
self.flag = 0
self.home()
def home(self):
# colors
black = (13, 13, 13)
light_black = (36, 36, 36)
# Pause Button
self.pause_btn = QtWidgets.QPushButton(self)
self.pause_btn.setText("Pause")
self.pause_btn.setShortcut("p")
self.pause_btn.move(0, 120)
self.pause_btn.clicked.connect(self.pause)
# Play Button
self.play_btn = QtWidgets.QPushButton(self)
self.play_btn.setText("Play")
self.play_btn.setShortcut("Space")
self.play_btn.move(150, 120)
self.play_btn.clicked.connect(self.play)
# Stop Button
self.stop_btn = QtWidgets.QPushButton(self)
self.stop_btn.setText("Stop")
self.stop_btn.setShortcut("s")
self.stop_btn.move(300, 120)
self.stop_btn.clicked.connect(self.stop)
# color for the window
color = QColor(70, 70, 70)
# Volume_Up Button
self.vup_btn = QtWidgets.QPushButton(self)
self.vup_btn.setText("V(+)")
self.vup_btn.setShortcut("+")
self.vup_btn.move(300, 160)
self.vup_btn.clicked.connect(self.volume_up)
# Volume_Down Button
self.vdown_btn = QtWidgets.QPushButton(self)
self.vdown_btn.setText("V(-)")
self.vdown_btn.setShortcut("-")
self.vdown_btn.move(0, 160)
self.vdown_btn.clicked.connect(self.volume_down)
# Seek Slider
self.slider = QSlider(Qt.Horizontal, self)
self.slider.setGeometry(20, 75, 350, 20)
# Volume Slider
self.v_slider = QSlider(Qt.Horizontal, self)
self.v_slider.setGeometry(120, 165, 160, 20)
self.v_slider.setMinimum(0)
self.v_slider.setMaximum(100)
self.v_slider.setValue(70)
self.volume_value = self.v_slider.value()
self.v_slider.valueChanged.connect(self.slider_value_changed)
print(self.v_slider.value() / 100)
def msg(self, title, message):
msg1 = QtWidgets.QMessageBox()
msg1.setWindowIcon(QtGui.QIcon("icon"))
msg1.setWindowTitle(title)
msg1.setText(message)
msg1.setStandardButtons(QtWidgets.QMessageBox.Ok)
msg1.exec_()
def open_mp3(self):
name = QtWidgets.QFileDialog.getOpenFileName(self)
format = os.path.splitext(name[0])
if format[1] == ".mp3":
self.audio = MP3(name[0])
self.duration = self.audio.info.length//1
self.min = int(self.duration // 60)
self.sec = int(self.duration % 60)
self.total_time = str(self.min) + ":" + str(self.sec)
print(self.total_time)
self.slider.setMaximum(self.duration)
self.slider.setMinimum(0)
time = []
time.append(self.total_time)
self.label = QtWidgets.QLabel(self)
self.label.setText(self.total_time)
self.label.setFont(QtGui.QFont("Arial", 9))
self.label.adjustSize()
self.label.move(373, 77)
song = name[0]
pg.mixer.music.load(song)
pg.mixer.music.play(1)
pg.mixer.music.set_volume(self.v_slider.value()/100)
self.label = QtWidgets.QLabel(self)
self.label.setText(song)
self.label.setFont(QtGui.QFont("Arial", 15))
self.label.adjustSize()
self.label.move(0, 36)
self.label.show()
threading_1 = threading.Thread(target=self.cur_time).start()
else:
self.msg("Invalid Format", "Choose A .Mp3 File Only!")
volume_level = pg.mixer.music.get_volume()
print(volume_level)
def cur_time(self):
true = 1
while true == 1:
if self.flag == 0:
self.m_time = pg.mixer.music.get_pos()
self.mm_time = self.m_time * 0.001
self.s_time = self.mm_time // 1
self.slider.setValue(self.s_time)
print(self.s_time)
self.slider.sliderMoved.connect(self.seek_changed)
if self.s_time == -1:
self.slider.setValue(0)
true = 2
if self.flag == 1:
print(self.s_time)
def seek_changed(self):
print(self.slider.value())
pg.mixer.music.set_pos(self.slider.value())
def slider_value_changed(self):
self.volume_value = self.v_slider.value()
pg.mixer.music.set_volume(self.v_slider.value()/100)
def volume_up(self):
self.volume_value = self.volume_value + 10
self.v_slider.setValue(self.volume_value)
if self.volume_value >= 100:
self.volume_value = 100
pg.mixer.music.set_volume(self.v_slider.value() / 100)
print(self.v_slider.value() / 100)
def volume_down(self):
self.volume_value = self.volume_value - 10
self.v_slider.setValue(self.volume_value)
if self.volume_value <= 0:
self.volume_value = 0
pg.mixer.music.set_volume(self.v_slider.value() / 100)
print(self.v_slider.value() / 100)
def pause(self):
pg.mixer.music.pause()
self.flag = 1
def stop(self):
pg.mixer.music.stop()
self.flag = -1
def play(self):
pg.mixer.music.unpause()
self.flag = 0
def close_app(self):
choice = QtWidgets.QMessageBox.question(
self, "QUIT", "You Sure You Wanna Quit?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
if choice == QtWidgets.QMessageBox.Yes:
sys.exit()
else:
pass
def items(self):
layout = QtWidgets.QVBoxLayout(self)
song_name = QtWidgets.QFileDialog.getOpenFileName(self)
widget = QtWidgets.QListWidget()
widget.setAlternatingRowColors(True)
widget.setDragDropMode(
QtWidgets.QAbstractItemView.InternalMove)
widget.addItems([str(i) for i in range(1, 6)])
layout.addWidget(widget)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = window()
win.show()
sys.exit(app.exec_())
谢谢。
答案 0 :(得分:2)
主要问题是您仍在运行threading.Thread
,因此当QtApplication被“关闭”时,该程序仍然有效。
您应该真正避免使用while循环检查当前位置,因为每次循环循环时,它将调用request该值,从而消耗了大量不必要的CPU资源。
另外,每次循环循环时,您都将liderMoved信号连接到seek_changed,这是坏。
使用QTimer代替,它将更新光标位置,而不会使过程超载:
# create a timer in the window __init__
self.cursor_updater = QtCore.QTimer(interval=100, timeout=self.cur_time)
#...
def cur_time(self):
# ignore the update if the user is seeking
if self.slider.isSliderDown():
return
self.slider.setValue(pg.mixer.music.get_pos() * .001)
然后,您只需要在音乐开始播放(或取消暂停)时启动计时器,并在您停止或暂停音乐时停止播放即可。
也就是说,您的代码还有其他问题。
sys.exit()
和优雅地退出,也无法通过它们自己的quit()
函数退出,因为很可能否则它们都将挂在自己的循环中而无法真正退出,从而保持进程运行(循环几乎什么也不做)并消耗大量资源。我不是使用pygame 和 PyQt的专家,但据我所知,您可以改为致电os._exit(0)
。closeEvent()
,因为如果用户仅关闭窗口而不退出,则不会有任何确认对话框,并且不会调用上述退出过程。set_pos()
,您都需要跟踪位置,并据此计算实际值。