1

我有一个 mp3 文件列表,每当按下不同的按钮(每个按钮一个文件)时,我都试图通过 pygame 播放这些文件。由于这些文件的数量不定,我只是实现了一个 for 循环,并且我有一个AudioPlayer类,我每次实例化如下:

import sys, pygame
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class AudioPlayer(QObject):
    def __init__(self, filename):
        super().__init__()
        self.filename = filename
        print("Created " + filename)

    def play(self):
        print("Playing " + self.filename)
        pygame.mixer.music.load(self.filename)
        pygame.mixer.music.play()

class Session(QMainWindow):
    def __init__(self):
        super().__init__()
        self.mainWid = QWidget(self)
        self.vbox = QVBoxLayout()
        self.mainWid.setLayout(self.vbox)
        self.setCentralWidget(self.mainWid)
        self.show()

        pygame.mixer.init()

        filenames = [r'C:\...\file1.mp3', r'C:\...\file2.mp3']

        for filename in filenames:
            playButton = QPushButton('Play', self)
            localPlay = AudioPlayer(filename)
            playButton.clicked.connect(localPlay.play)
            self.vbox.addWidget(playButton)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    Session()
    sys.exit(app.exec_())

我的问题只是当我按下按钮时文件没有播放,消息也没有被打印出来;就像插槽永远不会被调用:

admin@home> python main2.py
Created C:\...\file1.mp3
Created C:\...\file2.mp3
admin@home>

如果我在循环之外手动播放文件,就像这样,它可以工作:

class Session(QMainWindow):
    def __init__(self):

        # ...

        filenames = [r'C:\...\file1.mp3', r'C:\...\file2.mp3']

        pygame.mixer.music.load(filenames[0])
        pygame.mixer.music.play()

如您所见,我确保 AudioPlayer 继承了 QObject 并调用了__init__,所以我相信它应该能够接收信号。那么这里发生了什么?是局部变量问题吗?

4

1 回答 1

2

问题是由于AudioPlayer在循环中创建的对象是局部变量,因此当它们完成运行构造函数时,它们会从内存中删除。有两种可能的解决方案,第一种是使它们成为类的属性,或者第二种是将它们传递给父级,因为它们继承自QObject,我将使用第二种方法:

class AudioPlayer(QObject):
    def __init__(self, filename, parent=None):
        super().__init__(parent=parent)
        self.filename = filename
        print("Created " + filename)

    @pyqtSlot()
    def play(self):
        print("Playing " + self.filename)
        pygame.mixer.music.load(self.filename)
        pygame.mixer.music.play()

class Session(QMainWindow):
    def __init__(self):
        super().__init__()
        self.mainWid = QWidget(self)
        self.vbox = QVBoxLayout()
        self.mainWid.setLayout(self.vbox)
        self.setCentralWidget(self.mainWid)
        self.show()

        pygame.mixer.init()

        filenames = [r'C:\...\file1.mp3', r'C:\...\file2.mp3']

        for filename in filenames:
            playButton = QPushButton('Play', self)
            localPlay = AudioPlayer(filename, self)
            playButton.clicked.connect(localPlay.play)
            self.vbox.addWidget(playButton)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Session()
    sys.exit(app.exec_())
于 2018-01-21T14:29:39.607 回答