1

Tkinterを使用してPythonでGUIプログラムを作成していますが、CPUをすべて使用せずにキー押下が発生しているかどうかを確認する方法が必要です。現在、スレッドモジュールを使用して、インターフェイス(Tkinter)をフリーズせずにキーが押されたことを確認するスレッドを開始しています。スレッド内のwhileループでwin32api.GetKeyState()を使用して、ウィンドウにフォーカスがない場合でもキーが押されているかどうかを判断できる必要があるため、キーのステータスを常にチェックします。問題は、スレッドを開始した瞬間にプログラムが100%CPUを使用することです。time.sleep()をループに入れると、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'がありません

4

1 に答える 1

7

現在のキーボードの状態をポーリングするのではなく、主要なイベントをキャッチしたい。

TkInterドキュメントのイベントとバインディングを参照してください。これには、必要なことを正確に実行する簡単な例があります(さらに、Win32のみではなくクロスプラットフォームです)。

そして、これは一般的にすべてのGUIプログラミング(さらに言えばネットワークサーバー)の問題であり、答えは常に同じです。スレッドの有無にかかわらず、非ブロッキングの「現在のXステータスのチェック」呼び出しを直接使用することはありません。メインスレッドでは、イベントループに「Xステータスが変更されたときに関数を呼び出す」ように要求するか、バックグラウンドスレッドを作成して、ブロッキング「Xが発生するまで永遠に待つ」呼び出しを行います。

イベントループに関するウィキペディアのページには、実際にはこれについてかなり良い説明があります。


編集したバージョンを見ると、まったく新しい問題が発生しています。

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。の方法でself.GetCoordsない限り、あなたはすることができません。それがまさにエラーメッセージの意味です。GetCoordsselfAttributeError: Application instance has no attribute 'GetCoords'

ただし、プレフィックスを削除するだけで、ローカル関数を渡すことができます。これであなたの考えがうまくいくかどうかはわかりませんが(そのように閉じることができるかどうかわからないため)、…試してみてください。GetCoordsself.StringVar

または、メソッドをから移動してパラメータを指定するだけでメソッドを作成できます。 次に、にアクセスして、バインドされたメソッドを取得できます。これは、目的どおりに渡すことができます。ただし、その場合、は内部変数であるため、アクセスできなくなります。これを修正するには、の代わりに、および(およびその他の場所)のどこでも使用して、そのローカル変数をメンバー変数に変更します。GetCoordsdef __init__selfself.GetCoordscoords__init__self.coords__init__GetCoordscoords

于 2013-01-10T00:34:28.217 に答える