Pyglet在我的Python Chip-8模拟器中不注册按键按下,即使没有使用keyboard模块。

huangapple go评论70阅读模式
英文:

Pyglet not registering key presses unless I import keyboard module in my Python Chip-8 emulator even though it's not being used

问题

背景

我正在开发一个 Python Chip-8 模拟器 Chipy。我使用 Pyglet 来显示精灵并处理按键事件。

我实现屏幕和键盘功能的方式是将它们放在不同的文件中,但在同一个模块中,如下所示。

screen.py

from pyglet.window import Window

window = Window(args, kwargs)

"""
与在屏幕上显示相关的所有函数
"""

keyboard.py

from .screen import window

@window.event
def on_key_press():
  # 处理按键按下事件

@window.event
def on_key_release():
 # 处理按键释放事件

问题

实际的操作码在一个不同的文件中处理,该文件使用了 screen.py 模块的某些功能,但没有使用 keyboard.py 模块。但是,如果我不将键盘模块与屏幕一起导入,Pyglet 将不会注册按键事件。

control_unit.py

from chipy.peripherals import screen, keyboard

# 处理所有操作码
# 使用屏幕模块
# 键盘模块是未使用的导入

上述文件可以正常工作,但如果我删除未使用的导入 keyboard,Pyglet 将不会注册按键事件。我不知道是什么原因导致了这种行为,或者是否有一种方法使代码更有组织性?

我在 Pyglet 文档中浏览了键盘事件,但没有找到任何可以帮助理解这种行为的内容。

英文:

Background

I'm working on a Python chip-8 emulator Chipy.
And I'm using Pyglet to display sprites and handle keypresses.

The way I implemented the screen and keyboard functions are in separate files but in the same module, as follow.

screen.py

from pyglet.window import Window

window = Window(args, kwargs)

"""
All the functions related to displaying things on screen
"""

keyboard.py

from .screen import window

@window.event
def on_key_press():
  # Handled key presses

@window.event
def on_key_release():
 # Handled key releases

Issue

The actual opcodes are being handled in a different file, which uses the screen.py module for some functionalities but not the keyboard.py module. But if I do not import the keyboard along with the screen, pyglet won't register keypresses.

control_unit.py

from chipy.peripherals import screen, keyboard

# Handles all the opcodes
# Uses screen
# keyboard is an unused import

Everything works fine with above file, but If I were to remove the unused import keyboard, pyglet will stop registering keypresses. I don't know what is causing this behaviour or is there a work around to make the code more organized?

I skimmed through the keyboard events in the Pyglet documentation but didn't find anything that could help understand this behaviour.

答案1

得分: 1

可能会有一些混淆,keyboard.py 本身并不是未使用的。它可能在 control_unit 中没有使用,但从我所能看到的情况来看,它被你的应用程序用于注册 pyglet 键盘事件。

@window.event 本质上是一个包装器,它将该函数注册到你的窗口,以便它可以接收键盘输入。如果你没有导入该模块,那么该包装器不会运行并注册它。因此,你应该在应用程序启动后在你的窗口上注册任何事件,所以在导入 keyboard.py 时导入 screen.py 是一个简单的修复方法。

至于使代码更有组织性,有几种方法可以做到。主要是使用事件系统。你可以使用一个类来管理你的窗口和事件,像这样:

class MyApplication:
    def __init__(self):
        self.window = pyglet.window.Window(width, height)
        
        self.window.push_handlers(self)
        
    def on_key_press(self, symbol, modifiers):
        print("按键被按下了!")

这意味着 MyApplication 实例充当事件的处理程序,因此它将自动接收窗口接收到的任何事件。

如果你想要更有组织性,也可以为另一个类执行此操作。你甚至可以拥有多种这些处理程序的类型,以使事件沿着堆栈传递。

class ApplicationInputHandler:
    def __init__(self, window):
        window.push_handlers(self)
        
    def on_key_press(self, symbol, modifiers):
        print("按键被按下了!")

我建议访问这里的文档以获取更多信息:https://pyglet.readthedocs.io/en/latest/programming_guide/events.html

你还可以访问 Pyglet Discord 与其他人一起讨论,以获取其他建议。

英文:

There may be a little confusion, keyboard.py is not unused per-se. It may be unused in control_unit, but from what I can tell it's being used by your application to register the pyglet keyboard events.

@window.event is essentially a wrapper that registers that function to your window so it can receive the keyboard input. If you are not importing the module, then that wrapper is not going to run and register it. So you should be registering any events on the application start after your Window, so importing keyboard.py when screen.py is imported is an easy fix.

As far as making the code more organized there are a few ways to do it. Mainly with the event system. You could use a class to manage your window and events this way:

For example:

class MyApplication:
    def __init__(self):
        self.window = pyglet.window.Window(width, height)
        
        self.window.push_handlers(self)
        
    def on_key_press(self, symbol, modifiers):
        print("I got pressed!")

This means that the MyApplication instance is acting as a handler for the events, so it will automatically receive any events the Window gets.

You can do this for another class as well if you want it even more organized. You could even have multiple kinds of these handlers to have the events travel down the stack.

class ApplicationInputHandler:
    def __init__(self, window):
        window.push_handlers(self)
        
    def on_key_press(self, symbol, modifiers):
        print("I got pressed!")

I would visit the docs here for more information: https://pyglet.readthedocs.io/en/latest/programming_guide/events.html

You can also visit the Pyglet Discord to discuss it openly with others for additional suggestions.

huangapple
  • 本文由 发表于 2023年6月1日 07:33:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76377862.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定