I am having issues with my software. In my piano software if I keep pressing a key on the keyboard then it is making multiple repeated same tones of that particular key. But actually I need a single tone until the release of that particular key. I'm providing a part of my code that detects the keyPress event and calls the corresponding method. So what should be the changes that I've to do with my code??
def keyPressEvent(self, event):
if type(event) == QtGui.QKeyEvent and event.key() == QtCore.Qt.Key_A :
self.Playnote('/home/hemanth/hemanth/Piano/C.mp3')
self.ui.pushButton.animateClick(100)
if type(event) == QtGui.QKeyEvent and event.key() == QtCore.Qt.Key_S:
self.Playnote('/home/hemanth/hemanth/Piano/D.mp3')
self.ui.pushButton_2.animateClick(100)
You should check event.isAutoRepeat()
to determine if the event is caused by keyboard autorepeat or an actual keypress. If it is an autorepeat, ignore that press.
Since a keyPressEvent will always receive a QKeyEvent, you won't need to check its type at all. You can already start by simplifying this example:
def keyPressEvent(self, event):
key = event.key()
if key == QtCore.Qt.Key_A :
self.Playnote('/home/hemanth/hemanth/Piano/C.mp3')
self.ui.pushButton.animateClick(100)
elif key == QtCore.Qt.Key_S:
self.Playnote('/home/hemanth/hemanth/Piano/D.mp3')
self.ui.pushButton_2.animateClick(100)
Now, like you said, this will simply fire your sounds every time a key is pressed. There would be a few steps needed to get the entire functionality you require.
- The
Playnote
needs to be able to keep looping until told to stop
- You need to keep a reference to that
Playnote
object in order to stop it later
- A keyReleaseEvent will have to use the
Playnote
reference to stop it
1) Playnote
needs to loop
If you are using Phonon for the functionality of this Playnote
, then you can use an approach suggested by the docs. This would be to connect the Media Objects' aboutToFinish
signal to a method that will enqueue another version of the same media source.
It might look something like this:
class Playnote(QtCore.QObject):
def __init__(self, soundFile, parent=None):
super(Playnote, self).__init__(parent)
self._isStopped = True
self.mediaSource = Phonon.MediaSource(soundFile)
self.mediaObject = Phonon.MediaObject(self)
self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
Phonon.createPath(self.mediaObject, self.audioOutput)
self.mediaObject.setCurrentSource(self.mediaSource)
self.mediaObject.aboutToFinish.connect(self.doRequeue)
def doRequeue(self):
if not self._isStopped:
self.mediaObject.enqueue(self.mediaSource)
def play(self):
self._isStopped = True
# other code here
def stop(self):
self._isStopped = False
# other code here
You are connecting that signal to a method that will requeue the same sound if the player has not been stopped.
2) Need a Playnote
object
When you start your sound with the keyPressEvent, you will have to store a reference to the object that is now playing. Maybe you can create a dictionary, and store a mapping of the key to the current playing object?
# in your class
self.keysPlaying = {}
def keyPressEvent(self, event):
key = event.key()
if key == QtCore.Qt.Key_A :
c_note = Playnote('/home/hemanth/hemanth/Piano/C.mp3')
self.keysPlaying['c'] = c_note
3) keyReleaseEvent stops Playnote
object
Now that you have started, and looped your sound, you can use the reference to stop it later in a keyReleaseEvent:
def keyReleaseEvent(self, event):
key = event.key()
if key == QtCore.Qt.Key_A :
note = self.keysPlaying.get('c', None)
if note:
note.stop()
self.keysPlaying['c'] = None