Tkinter 框架无法识别按键

Tkinter Frame Not Recognizing Keypresses

这个问题不是这个问题的重复:Why doesn't the .bind() method work with a frame widget in Tkinter?

如您所见,我在 game_frame() 方法中将焦点设置到当前帧。

我正在 Python 中编写一个 Chip-8 模拟器,并将 Tkinter 用于我的 GUI。模拟器是 运行ning,但我无法让 Tkinter 识别按键。这是我的代码:

def game_frame(self):
    self.screen = Frame(self.emulator_frame, width=640, height=320)
    self.screen.focus_set()
    self.canvas = Canvas(self.screen, width=640, height=320, bg="black")
    self._root.bind("<KeyPress-A>", self.hello)
    for key in self.CPU.KEY_MAP.keys():
        print(key)
        self.screen.bind(key, self.hello)
    self.screen.pack()
    self.canvas.pack()

def hello(self, event):
    if event.keysym in self.CPU.KEY_MAP.keys():
        self.CPU.keypad[self.CPU.KEY_MAP[event.keysym]] = 1
        self.CPU.key_pressed = True
        self.CPU.pc += 2
    sys.exit()

def run_game(self, event):
    self.game_frame()
    self.CPU.load_rom("TANK")
    while True:
        self._root.update()
        self.after(0, self.CPU.emulate_cycle)

你能帮我找出问题所在吗?我认为这可能与我的游戏循环干扰键绑定有关,但我不确定。当我 运行 游戏时,hello 方法永远不会被调用,因为程序在无限循环中继续 运行 并且永远不会退出,无论按下什么键。谢谢!

问题可能是由两件事引起的。没有看到你所有的代码,就不可能肯定地说。

首先,您绑定的是大写字母 "A" 而不是小写字母 "a" -- 当您按下大写字母 A 时,您是否测试过绑定是否有效?

此外,您使用的 afterupdate 不正确。您可能使事件循环处于饥饿状态,从而阻止它处理按键操作。定期 运行 函数的正确方法是拥有一个(重新)安排自身的函数。

class CPU_Class():
    ...
    def run_cycle(self):
        self.emulate_cycle()
        self._root.after(1, self.run_cycle)

需要注意两点:

  1. 不要使用 after(0, ...) -- 你需要给 tkinter 至少 1 毫秒左右的时间来处理其他事件。
  2. run_cycle函数负责运行ning一个周期,然后将下一个周期调度到运行以后。

一旦你这样做了,你就不再需要你的 while 循环了。您只需调用 run_cycle 一次,即可启动 CPU 运行ning.