Как обрабатывать несколько нажатых одновременно клавиш в Kivy?

Я планировал сделать небольшую кроссплатформенную игру с kivy, и когда я тестировал способ ввода с клавиатуры на ПК, меня ждал небольшой сюрприз.

Kivy, похоже, не обрабатывает несколько нажатых клавиш одновременно с событиями on_keyboard_down, когда вы нажимаете более одной клавиши одновременно в kivy, класс клавиатуры, используемый в официальной документации, передает последнюю нажатую клавишу при изменении всех нажатых клавиш в данный момент.

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

Это код, который я написал для интерактивного приветствия с клавиатурой.

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter
from kivy.core.window import Window

class MyApp(App):
    def __init__(self, **kwargs):
        super(MyApp, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down = self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down = self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print str(keyboard)+' '+str(keycode[1])+' '+str(text)+' '+str(modifiers)
        if keycode[1] == 'w':
            self.moveable.y += 1

        if keycode[1] == 's':
            self.moveable.y -= 1

        if keycode[1] == 'd':
            self.moveable.x += 1

        if keycode[1] == 'a':
            self.moveable.x -= 1 


    def build(self):
        self.moveable = Scatter()
        self.moveable.add_widget( Label(text = 'Hello moving world!') )
        return self.moveable

if __name__ == '__main__':
    MyApp().run()

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

Извините, если вопрос по какой-то причине неуместен, я пытался найти на него ответ, но не смог, так что вот он.

Спасибо вам большое заранее, если вы можете помочь с этим.


person Pabloski gl    schedule 23.03.2014    source источник


Ответы (1)


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

(Редактировать: перечитав свой пост, я думаю, что вы вообще не хотите это менять и неправильно поняли, как работать с вводом с клавиатуры, см. вторую часть этого поста)

Я почти уверен, что это связано с настройками операционной системы, а не с Kivy. Существует много дискуссий об изменении этого значения в Интернете, если вы хотите, например, в Linux вы, вероятно, можете сделать xset r rate [delay] [rate], например. xset r rate 200 25, или в различных средах рабочего стола для этого есть настройка графического интерфейса. Подобные вещи справедливы и для окон. Ключевое слово, кажется, «задержка повтора».

Тем не менее, я не уверен, почему это действительно имеет значение. Kivy сообщает вам, когда клавиша нажата и когда она отпущена, и вы можете выполнять событие так часто, как вам нравится, в течение этого времени, если хотите. Почему так важно, продолжает ли ОС посылать вам дополнительные нажатия клавиш?

Kivy, похоже, не обрабатывает несколько нажатых клавиш одновременно с событиями on_keyboard_down, когда вы нажимаете более одной клавиши одновременно в kivy, класс клавиатуры, используемый в официальной документации, передает последнюю нажатую клавишу при изменении всех нажатых клавиш в данный момент.

Я думаю, вы можете неправильно понять, как Kivy представляет вам эту информацию. Когда клавиша нажата, kivy передает вам событие on_key_down для этой клавиши. Когда он освобождается, kivy передает событие on_key_up для этого ключа (ваша программа ничего с этим не делает). Между этими событиями вы знаете, что клавиша все еще нажата, и не имеет значения, продолжает ли система кормить вас поддельными нажатиями клавиш.

Изменить: вот модифицированная версия вашей программы, которая также печатает информацию о событии on_key_up:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter
from kivy.core.window import Window

class MyApp(App):
    def __init__(self, **kwargs):
        super(MyApp, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down = self._on_keyboard_down)
        self._keyboard.bind(on_key_up = self._on_keyboard_up)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down = self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, *args):
        print 'down', args

    def _on_keyboard_up(self, *args):
        print 'up', args


    def build(self):
        self.moveable = Scatter()
        self.moveable.add_widget( Label(text = 'Hello moving world!') )
        return self.moveable

if __name__ == '__main__':
    MyApp().run()
person inclement    schedule 23.03.2014
comment
Ну и правда, вопрос какой-то глупый все-таки был... Большое спасибо за помощь, чувак! Я новичок в стеке, я должен удалить вопрос для очевидности или что-то в этом роде? - person Pabloski gl; 23.03.2014
comment
Нет, не беспокойтесь об этом! Ошибаться - это нормально, и это случается со всеми :) - person inclement; 23.03.2014
comment
Как я могу что-то делать, пока ключ не нажат? Могу ли я запланировать что-то и повторить это, пока для флага все еще установлено значение «Истина» (изначально установлено значение «Истина», когда клавиша нажата, и установлено значение «Ложь», когда клавиша нажата) - или есть лучший способ? - person Zelphir Kaltstahl; 13.07.2015
comment
@Zelphir Если вы хотите выполнить повторяющееся действие, это будет нормально, хотя в зависимости от структуры вашего приложения другие вещи могут быть более естественными или лучшими. - person inclement; 13.07.2015