PyQt 中的 QKeyPress 事件

5

我在使用软件时遇到了问题。在我的钢琴软件中,如果我持续按住键盘上的一个键,则会发出多个重复的同一音调。但实际上,我需要的是在松开该特定键之前仅发出单个音调。我提供了一个检测keyPress事件并调用相应方法的代码片段。那么我应该怎样更改我的代码?

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)
2个回答

6

由于keyPressEvent始终会接收到QKeyEvent,因此您根本不需要检查其类型。您已经可以通过简化此示例来开始:

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)

现在,像你说的那样,每按一次键就会触发声音。需要几个步骤才能获得所需的完整功能:
  1. Playnote需要能够循环播放直到停止。
  2. 您需要保留对该Playnote对象的引用,以便稍后停止它。
  3. keyReleaseEvent将使用Playnote引用来停止它。

1)Playnote需要循环播放

如果您正在使用Phonon实现此Playnote的功能,则可以使用文档建议的方法。这是将媒体对象的aboutToFinish信号连接到一个方法,该方法将排队另一个相同媒体源的版本。

可能看起来像这样:

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

你正在将该信号连接到一个方法,如果播放器没有停止,则该方法将重新排队相同的声音。
2) 需要一个Playnote对象
当你使用keyPressEvent启动声音时,你需要存储一个对正在播放的对象的引用。也许你可以创建一个字典,并将键映射到当前播放对象?
# 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停止Playnote对象

现在,您已经启动并循环播放声音,可以使用引用在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

6

您应该检查event.isAutoRepeat()来确定事件是由键盘自动重复还是实际按键引起的。如果是自动重复,请忽略该按下事件。


@ Brian Campbell:谢谢,它现在能用了 :) 我上传了另一个问题。你能帮我吗? - Hemanth Raveendran
@HemanthRaveendran:这难道不仅仅解决了你的问题的一小部分吗?如果你按下键超过一次,它不还是会有同样的问题吗? - jdi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接