我今天已经问过这个问题,但事实证明,为了使我的代码更具可读性,我再次简化了这种情况。现在我将尝试更详细地讲述一切。
我的代码包含两个类 -MyThread和MyWindow.
一个MyWindow应用程序窗口是用一个按钮创建的btn。btn绑定到new_thread调用方法的方法choose_dir。choose_dir调用目录选择对话框并返回所选目录的路径。如果choose_dir返回目录路径,new_thread则创建一个新线程,该线程是MyThread.
在一个新线程中,我计划提取MP3-файла所选目录中每个人的标签。
choose_files类方法MyThread,遍历所选目录中的所有 MP3 文件,将每个文件的路径传递给extract_tags. extract_tags提取音乐文件的各种标签,其中应包括文件的持续时间。为了提取持续时间,我创建QMediaPlayer了一个 ,将extract_tags. 之后,我创建QTimer了一个应该调用方法的extract_duration. extract_duration必须检索文件的长度。但是,由于某种原因,该方法的代码extract_duration没有被执行。
请告诉我如何修复代码?
from PyQt5 import QtCore, QtWidgets, QtMultimedia
from pathlib import Path
class MyThread(QtCore.QThread):
singlTimer = QtCore.pyqtSignal()
def __init__(self, directory, parent=None):
QtCore.QThread.__init__(self, parent)
self.directory = directory
def run(self):
print('THREAD: run')
self.choose_files()
def choose_files(self):
pathlist = Path(self.directory).glob('**/*.mp3')
if pathlist:
for path in pathlist:
self.path = str(path).replace('\\', '/')
print(self.path)
self.extract_tags()
def extract_tags(self):
# тут достаю теги файла self.path
self.player = QtMultimedia.QMediaPlayer()
self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(self.path)))
self.player.play()
self.player.setVolume(0.0)
QtCore.QTimer.singleShot(150, self.extract_duration)
def extract_duration(self):
d = self.player.duration()
m = d // 1000 // 60
s = d // 1000 % 60
self.length = f'{m:1}:{s:02}'
print(self.length)
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__(parent)
box = QtWidgets.QHBoxLayout(self)
btn = QtWidgets.QPushButton('Button', clicked = self.new_thread)
box.addWidget(btn)
def new_thread(self):
print('CHOOSE DIRECTORY BUTTON: click')
directory = self.choose_dir()
if directory:
self.mythread = MyThread(directory)
self.mythread.started.connect(self.on_started)
self.mythread.finished.connect(self.on_finished)
self.mythread.start()
def choose_dir(self):
# Вызываю диалоговое окно выбора папки
print('dialog window')
drive = Path().absolute().drive + '/'
dir_1 = QtWidgets.QFileDialog.getExistingDirectory(self,
'Open a folder',
drive,
QtWidgets.QFileDialog.ShowDirsOnly)
if dir_1:
return dir_1
def on_started(self):
print('THREAD: start')
def on_finished(self):
print('THREAD: finish')
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())
升级版:
from PyQt5 import QtCore, QtWidgets, QtMultimedia
from pathlib import Path
class MyThread(QtCore.QThread):
singlTimer = QtCore.pyqtSignal(str)
def __init__(self, directory, parent=None):
QtCore.QThread.__init__(self, parent)
self.directory = directory
self.length = None
def run(self):
print('THREAD: run\n')
self.choose_files()
def choose_files(self):
pathlist = Path(self.directory).glob('**/*.mp3')
if pathlist:
for path in pathlist:
self.index = 0 # +++
self.path = str(path).replace('\\', '/')
self.singlTimer.emit(self.path)
# update
while self.index != 1:
QtCore.QThread.msleep(20)
print('не хватает времени')
if self.length:
self.extract_duration()
# update
def extract_duration(self): # update
print(self.length) # update
print('a') # update
self.length = None
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__(parent)
box = QtWidgets.QHBoxLayout(self)
btn = QtWidgets.QPushButton('Button', clicked = self.new_thread)
box.addWidget(btn)
def new_thread(self):
print('CHOOSE DIRECTORY BUTTON: click')
directory = self.choose_dir()
if directory:
self.mythread = MyThread(directory)
self.mythread.started.connect(self.on_started)
self.mythread.finished.connect(self.on_finished)
self.mythread.singlTimer.connect(self.on_singlTimer)
self.mythread.start()
def choose_dir(self):
# Вызываю диалоговое окно выбора папки
print('dialog window')
drive = Path().absolute().drive + '/'
dir_1 = QtWidgets.QFileDialog.getExistingDirectory(self,
'Open a folder',
drive,
QtWidgets.QFileDialog.ShowDirsOnly)
if dir_1:
return dir_1
def on_started(self):
print('THREAD: start')
def on_finished(self):
print('\nTHREAD: finish')
def on_singlTimer(self, path):
self.player2 = QtMultimedia.QMediaPlayer()
self.player2.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(path)))
self.player2.play()
self.player2.setVolume(0.0)
self.player2.durationChanged.connect(self.func_2)
def func_2(self):
d = self.player2.duration()
m = d // 1000 // 60
s = d // 1000 % 60
length = f'{m:1}:{s:02}'
self.mythread.length = length
self.mythread.index = 1 # +++
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())
流程是一件微妙的事情 :) 到目前为止,它的工作方式并没有什么不同。尝试。
更新
我纠正了你的第二个例子,它基本上有效。
while self.index != 1:,做,while index:或者while not index: