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)
4

2 回答 2

6

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

于 2012-04-06T18:52:32.527 回答
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
于 2012-04-06T19:19:11.617 回答