python - Program Doesn't Close After Quitting It In PyQt
问题描述
So, Recently I was trying to make an audio player using PyQt5, pygame, and mutagen. The program works pretty fine. But when I'm playing a song and try to quit the program, the program stops responding and the song continues to play. But this doesn't happen when a song is not playing, it works fine then.
Here is the Code:
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_())
Thanks In Advance.
解决方案
主要问题是您仍在threading.Thread
运行,因此当 QtApplication “关闭”时,程序仍然存在。
您真的应该避免使用 while 循环来检查当前位置,因为它会在每次循环循环时调用请求该值,从而消耗大量不必要的 CPU 资源。
此外,每次循环循环时,您都将 sliderMoved 信号连接到 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)
然后,您只需在每次音乐开始(或取消暂停)时启动计时器,并在您停止或暂停时停止。
也就是说,您的代码还有其他问题。
- pygame 和 Qt 运行它们自己的事件循环,因此您不能通过或它们自己的函数轻松优雅地退出,因为它们中的一个或两个可能只是挂在自己的循环中而无法真正退出,保持进程运行(循环几乎什么都不做)并消耗大量资源。我不是使用 pygame和PyQt 的专家,但据我所知,你可以打电话。
sys.exit()
quit()
os._exit(0)
- 应该注意窗口
closeEvent()
,因为如果用户只是关闭窗口而不退出,则不会有任何确认对话框,也不会调用上述退出过程。 - pygame.mixer.music.get_pos() “仅表示音乐播放了多长时间;它不考虑任何起始位置偏移”。因此,您需要在使用时跟踪位置
set_pos()
并相应地计算实际值。 - 你真的应该考虑使用布局,或者确保窗口大小是固定的,否则用户将能够将其调整为比界面更小的大小。
推荐阅读
- javascript - 在滚动条上更改汉堡菜单的颜色
- java - 即使将 Additivity 设置为 false,log4j ConsoleAppender 也会打印到控制台两次
- python - 如何根据另一列的值替换一列中的字符串?
- bash - sed shell 与 jenkins 部署
- apache-kafka - MSK Kafka:请解释为什么 ZookeeperConnectString 列出了多个端点以及我应该如何使用它们
- sql - 包含“。”的自动创建的 bigquery 字段名称存在问题。
- c++ - 清除输入缓冲区
- r - 如何在包含两列的 Rmarkdown pdf 中插入全宽表格?
- javascript - 干杯。处理另一个函数的错误后无法在 TRY 体内获取数据
- android - Microsoft Teams - 如何从 Android Intent 启动 MS Teams