PyQt4 – удерживание клавиши обнаружено как частое нажатие и отпускание?

Я заметил необычное поведение, когда QApplication обрабатывает ключевые события, что ставит под угрозу небольшую игру, которую я надеялся сделать.

Удерживание клавиши приводит к многократному (и очень частому) вызову методов keyPressEvent, а затем keyReleaseEvent, вместо того, чтобы запускать keyPressEvent один раз и ждать отпускания клавиши для запуска другого (что является желаемым и, по общему признанию, ожидаемым поведением).

Это вызывает огромные проблемы с производительностью, до такой степени, что удерживание нескольких клавиш приводит к тому, что некоторые из них полностью игнорируются программой, предположительно из-за того, что страдает очередь событий.

Эта программа демонстрирует повторный вызов:

from PyQt4 import QtGui
import sys

class Window(QtGui.QWidget):

    def __init__(self):
        super(Window, self).__init__()

    def keyPressEvent(self, event):
        print 'PRESSED'
        event.accept()

    def keyReleaseEvent(self, event):
        print 'RELEASED'
        event.accept()

app = QtGui.QApplication(sys.argv)
Window().show()
sys.exit(app.exec_())

Эта программа (дурацкая графическая штука, которую я использовал для проверки игрового потенциала Qt) демонстрирует игнорирование новых нажатых клавиш при удержании существующих клавиш.

from PyQt4 import QtGui
import sys


class Window(QtGui.QWidget):

    def __init__(self):
        super(Window, self).__init__()
        self.resize(100,300)
        self.lower, self.upper = 10, -10
        self.keys = [81, 65, 90, 87, 83, 88, 69, 68, 67, 82, 70, 86, 84, 71,
        66, 89, 72, 78, 85, 74, 77, 73, 75, 44, 79, 76, 46, 80, 59, 47]
        self.dots = [self.lower] * len(self.keys)

    def keyPressEvent(self, event):
        pressed = event.key()
        if (pressed in self.keys):
            index = self.keys.index(pressed)
            self.dots[index] = self.height()+self.upper
            self.repaint()
        event.accept()

    def keyReleaseEvent(self, event):
        pressed = event.key()
        if (pressed in self.keys):
            index = self.keys.index(pressed)
            self.dots[index] = self.lower
            self.repaint()
        event.accept()

    def paintEvent(self, event):
        step = self.width() / (len(self.dots) + 1)
        painter = QtGui.QPainter()
        painter.begin(self)
        x, y = 0, 0
        for w in self.dots:
            i, j = x + step, w
            painter.drawLine(x, self.height() - y, i, self.height() - j)
            x, y = i, j
        painter.end()


app = QtGui.QApplication(sys.argv)
Window().show()
sys.exit(app.exec_())

Как вы можете заметить, запустив приведенную выше программу, удерживание более 3 или 4 клавиш приведет к тому, что новые пики не будут установлены, пока не будут отпущены удерживаемые в данный момент клавиши.

Как я могу предотвратить такое поведение, когда keyPressEvent срабатывает только один раз для клавиши, которая физически не была выпущена?


person Anti Earth    schedule 04.01.2013    source источник
comment
Я пришел к выводу, что это имеет отношение к этому: stackoverflow.com/questions/876852/ Как с этим бороться?   -  person Anti Earth    schedule 04.01.2013
comment
Это может быть более чем поздно, но многие клавиатуры в любом случае не поддерживают более 3 или 4 одновременных нажатий клавиш.   -  person JAB    schedule 18.11.2015


Ответы (1)


используя event.isAutoRepeat() может помочь

e.g.

def keyPressEvent(self, event):
    if event.isAutoRepeat():
        return
    pressed = event.key()
    if (pressed in self.keys):
        index = self.keys.index(pressed)
        self.dots[index] = self.height()+self.upper
        self.repaint()
    event.accept()
person eqzx    schedule 05.01.2013
comment
Это останавливает повторную перерисовку, но не события, занимающие драгоценное место в очереди событий, и поэтому новые нажатия клавиш по-прежнему игнорируются. - person Anti Earth; 05.01.2013