RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1105110
Accepted
MAXIM045
MAXIM045
Asked:2020-04-04 02:19:53 +0000 UTC2020-04-04 02:19:53 +0000 UTC 2020-04-04 02:19:53 +0000 UTC

为什么 QTimer 不起作用?(第 2 部分)

  • 772

我今天已经问过这个问题,但事实证明,为了使我的代码更具可读性,我再次简化了这种情况。现在我将尝试更详细地讲述一切。

我的代码包含两个类 -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_())
python
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    S. Nick
    2020-04-04T04:58:56Z2020-04-04T04:58:56Z

    流程是一件微妙的事情 :) 到目前为止,它的工作方式并没有什么不同。尝试。

    from PyQt5 import QtCore, QtWidgets, QtMultimedia
    from pathlib import Path
    
    class MyThread(QtCore.QThread):
        singlTimer = QtCore.pyqtSignal(str)                          # 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.path = str(path).replace('\\', '/')
                    self.singlTimer.emit(self.path)                  # +++ self.path
                    QtCore.QThread.msleep(500)                       # +++
    #                self.extract_tags()
                    if self.length:                                  # +++
                        self.extract_duration(self.length)           # +++
    
        def extract_duration(self, length):
            print(f'length !!!!!!!!!!!+++++++++++++++ {length}')
            QtCore.QThread.msleep(3000)  # <<<--- Запускайте здесь свою длительную задачу 
            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')
    
    # ++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv        
        def on_singlTimer(self, path):                                            # +++
            # тут достаю теги файла self.path 
            self.player = QtMultimedia.QMediaPlayer()
            self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(path)))   # path
            self.player.play()
            self.player.setVolume(0.0)
            QtCore.QTimer.singleShot(150, self.func_2)
    
        def func_2(self):                                                         # +++
            d = self.player.duration()
            m = d // 1000 // 60
            s = d // 1000 % 60
            length = f'{m:1}:{s:02}'
    
            self.mythread.length = length                                          # +++ !!!
    
            print(f'This doesn`t work :) ---> {d}')
    
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        window = MyWindow()
        window.setWindowTitle(' ')
        window.show()
        sys.exit(app.exec_())
    

    在此处输入图像描述


    更新

    我纠正了你的第二个例子,它基本上有效。

    • 不要将类属性设为临时变量,(self.index 和 self.path)
    • 不做while self.index != 1:,做,while index:或者while not index:
    • 请参阅有关示例文本的其他评论。

    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                                               #---
                    index = True                                                  # +++
                    path = str(path).replace('\\', '/')                           # -  self
                    self.singlTimer.emit(path)                                    # -  self
     #                while self.index != 1:
                    while index:                                                  # != 1:
                        QtCore.QThread.msleep(50)                                 # - 20 + 50
     #                    print('не хватает времени', index, self.length, path)
     # ----> это должно быть в цикле  `while`                   
                        if self.length:
                            self.extract_duration()
                            index = False                                         # +++ да
     # ---->
    
        def extract_duration(self):   
            print(f' получен length -> {self.length}')   
            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)
    
            # QMediaPlayer::durationChanged(qint64 duration)                    # !!!
            # Notifier signal for property duration.                            # !!!
            self.player2.durationChanged.connect(self.func_2)
    
        def func_2(self, d):                                                    # +++ d  !!!
     #        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_())
    
    • 1

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5