Python - 在不使用 100% cpu 的情况下检查按键

标签 python multithreading winapi tkinter keypress

我正在使用 Tkinter 在 Python 中编写一个 GUI 程序,我需要一种方法来检查是否正在发生按键,而无需使用我所有的 cpu。目前我正在使用线程模块启动一个线程,该线程将检查按键而不卡住界面(Tkinter)。我在我的线程内的 while 循环中使用 win32api.GetKeyState() 以便它不断检查键的状态,因为即使窗口没有焦点,它也需要能够判断键是否被按下。问题是程序在我启动线程时使用了 100% 的 cpu。如果我将 time.sleep() 放入循环中,它会显着减少 cpu 使用率,但在实际按键和它知道您正在按键的时间之间存在延迟。 有没有一种方法可以在按下按键的那一刻捕获按键,即使窗口没有焦点,也无需使用太多 cpu?

from Tkinter import *
import win32api

class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()

        coords = StringVar()

        Label(master=self, textvariable=coords).pack()

        def GetCoords():
            coords.set(str(win32api.GetCursorPos()))

        root.bind_all("<Scroll_Lock>", self.GetCoords)



root = Tk()
app = Application(master=root)
#root.wm_iconbitmap(default='INSERT ICON HERE')
#root.wm_title("TITLE OF PROGRAM")
#app.master.maxsize(640, 480)
app.master.minsize(640, 480)
app.master.resizable(0, 0)
app.mainloop()
app.quit()

该脚本给我以下结果: AttributeError:应用程序实例没有属性“GetCoords”

最佳答案

您想捕获按键事件,而不是轮询当前键盘状态。

参见 Events and Bindings在 TkInter 文档中,它有一个简单的示例,它完全符合您的要求(另外,它是跨平台的,而不是仅限 Win32)。

这通常是所有 GUI 编程(以及网络服务器)的一个问题,答案总是相同的。无论有无线程,您都不会直接有用地使用非阻塞“检查当前 X 状态”调用。在主线程中,您要求事件循环“当 X 状态改变时调用我的函数”,或者您创建一个后台线程并进行阻塞“永远等待直到 X 发生”调用。

Event loop 上的维基百科页面实际上对此有很好的描述。


查看您编辑的版本,您现在遇到了一个全新的问题:

class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()

        coords = StringVar()

        Label(master=self, textvariable=coords).pack()

        def GetCoords():
            coords.set(str(win32api.GetCursorPos()))

        root.bind_all("<Scroll_Lock>", self.GetCoords)

GetCoords 是在 Application.__init__ 中定义的局部函数。但是您正试图将它当作 Application 的方法来使用。除非 GetCoordsself 的方法,否则您不能执行 self.GetCoords。这正是错误消息 AttributeError: Application instance has no attribute 'GetCoords' 的意思。

但是您可以只传递局部函数GetCoords,只需去掉self. 前缀。我不确定这是否会按照您的想法进行(因为我不确定您是否可以像那样关闭 StringVar),但是……试试看。

或者,您可以制作 GetCoords 一个方法,只需将它移出 def __init__ 并给它一个 self 参数。然后您可以访问self.GetCoords,并获得一个绑定(bind)方法,您可以完全按照您的尝试传递该方法。但是,在那种情况下,它将无法再访问 coords,因为那是 __init__ 中的局部变量。要解决此问题,请将该局部变量更改为成员变量,方法是在 __init__GetCoords(以及其他任何地方)中各处使用 self.coords 坐标

关于Python - 在不使用 100% cpu 的情况下检查按键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14248901/

相关文章:

python - 日期格式化为月份

python - 使用 Django 的 Cron 示例

java - 构造函数中 "this"对象和 CurrentThread 之间

delphi - WebBrowser、IPersistStreamInit 和 javascript

python - 返回 num_dict 中值大于或等于 min_cutoff 的所有键(按设置)

python - python程序运行完成后如何自动重新运行?主管?

java - 线程本身是否有可能死锁?

wpf - 更新 UI 异步?

c++ - 从 C++ 应用程序查询堆

delphi - 如何获得笔记本电脑或台式机支持的最大内存大小?