Pirous
Pirous

Reputation: 11

QSoundEffect() doesn't play sounds when it's out of global scope

I'm making an app which copy files from one directory to another. I want it to produce sound when the process finishes. I can't figure out how to make QSoundEffect produce sounds when it's inside some function or class. The only time it works is when the code looks like the following:

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *


app = QApplication(sys.argv)
win = QMainWindow()

filepath = "C:\Windows\Media\Windows Error.wav"
sound = QSoundEffect()
sound.setSource(QUrl.fromLocalFile(filepath))
sound.play()
    
win.show()
sys.exit(app.exec_())

Why doesn't it work when code looks like that? How to make it work in a function or a class?

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *


def play_sound():
    filepath = "C:\Windows\Media\Windows Error.wav"
    sound = QSoundEffect()
    sound.setSource(QUrl.fromLocalFile(filepath))
    sound.play()


app = QApplication(sys.argv)
win = QMainWindow()
    
play_sound()

win.show()
sys.exit(app.exec_())

Upvotes: 1

Views: 1369

Answers (1)

eyllanesc
eyllanesc

Reputation: 243993

The problem is that "sound" is a local variable of the play_sound function so it will be eliminated when that method finishes executing which is almost instantaneous.

The solution is to extend the life cycle:

  • Python style: use a global variable

    sound = None
    
    def play_sound():
        filepath = "C:\Windows\Media\Windows Error.wav"
        global sound
        sound = QSoundEffect()
        sound.setSource(QUrl.fromLocalFile(filepath))
        sound.play()
    
  • Qt style: set a parent

    def play_sound():
        filepath = "C:\Windows\Media\Windows Error.wav"
        sound = QSoundEffect(QCoreApplication.instance())
        sound.setSource(QUrl.fromLocalFile(filepath))
        sound.play()
    

Upvotes: 1

Related Questions