キープレスイベントの辞書を使用してキャンバスアイテムを斜めに移動するために、tkinterで2つの同時キープレスイベントをプログラムするにはどうすればよいですか?

sw123456

以下は、キャンバスの周りで正方形を移動するためのコードです。矢印キーの押下イベントをキャプチャし、正方形を上下左右に移動します。一度に2つの矢印(たとえば、上下)を押しても、正方形は対角線上に移動しません。代わりに、必要な2つの方向のうちの1つだけに移動します。

このコードを変更して、正方形のスムーズな斜めの動きを可能にするにはどうすればよいですか。お時間をいただきありがとうございます。

from tkinter import *

x = 10
y = 10
a = 100
b = 100
direction = None

def move():
    global x_vel
    global y_vel
    global direction
    if direction is not None:
        canvas1.move(rect, x_vel,y_vel)
    window.after(33,move)

def on_keypress(event):
    global direction
    global x_vel
    global y_vel
    direction, x_vel, y_vel = dir_vel[event.keysym]

def on_keyrelease(event):
    global direction
    direction = None

dir_vel = {
    "Left": ("left", -5, 0),
    "Right": ('right', 5, 0),
    "Down": ('down', 0, 5),
    "Up": ('up', 0, -5),}


window = Tk()
window.geometry("400x200")

move()

#canvas and drawing
canvas1=Canvas(window, height = 200, width = 400)
canvas1.grid(row=0, column=0, sticky=W)
coord = [x, y, a, b]
rect = canvas1.create_rectangle(*coord, outline="#fb0", fill="#fb0")

#capturing keyboard inputs and assigning to function
window.bind_all('<KeyPress>', on_keypress)
window.bind_all('<KeyRelease>', on_keyrelease)
user3666197

どうすれば...イベントをプログラムできますか

プログラム部分: Tkinterは、UIの「前」で実際に外部刺激が発生することなく、それ自体でUIイベントを生成できます。したがって、「イベントをプログラムするにはどうすればよいですか」の部分は、次の方法で実行されます。

self.event_generate( <eventNameId>, **args ) # fire STIMULUS without User-interaction
#                                            # triggers <eventNameId>
#                                            # **args allow to set <keyword>=<value>
#                                            #        pairs for Event-fields,
#                                            #        that are passed to anEventHANDLER
#                                            #        via an-<Event>-object ...
#                                            #        ref below ( not the system-assigned ones, sure )

同時性の問題:

原則として、Tkinter / Pythonコードは順番に実行されます。2つのイベントを同時にインスタンス化する簡単な方法はありません。簡単に言えば、コードは本質的にシーケンシャルプロセッサであるため、ほぼ同時のイベントを何らかの形で模倣/検出する必要があります。

Bryan Oakleyが他の投稿で十分に説明しているように、UI検出は、ArrowUpおよび/またはを保持するArrowLeft、実際には自動生成されたUI- *イベントのシーケンスにつながる可能性があることに留意する必要があります。キーボードのタイプマティックレート設定。キーボードがキーが押されていることを検出すると、キーストロークを自動的に繰り返す役割を果たします...終了していません...)

入力刺激の読み方

Tkinterには、.event_generate()イベントを処理するための強力なMVC-Controller-Partメソッドのセットがあります(自然にUIで検出され、人工的に「注入」されます)。これは、タスクの他の側面にとって重要になります。

# eventInstanceMethods() bear many details about click/key/time/.widget()
#       <event>.char        on-{ <KeyPress> | <KeyRelease> }
#              .keysym      on-{ <KeyPress> | <KeyRelease> }
#              .keysym_num  on-{ <KeyPress> | <KeyRelease> }
#              .num         on-{ <Mouse-1>  | <Mouse-2> | ... } ? 4,5 == <MouseWheel>
#              .height      on-{ <Configure> }
#              .width       on-{ <Configure> }
#              .serial      <-- system-assigned Integer
#              .time        <-- system-assigned Integer ( .inc each msec )
#              .widget      <-- system-assigned <widget>-instance
#              .x           <-- system-assigned <Event>-in-<widget>-mouse-location.x
#              .y           <-- system-assigned <Event>-in-<widget>-mouse-location.y
#              .x_root      <-- system-assigned <Event>-on-<Screen>-mouse-location.x
#              .y_root      <-- system-assigned <Event>-on-<Screen>-mouse-location.y

このようなイベントを検出するために、Tkinterには次のメソッドが用意されています。

#                      |<<_aNamedEVENT_>>|<<______________________________aHANDLER>>|
#                      |or               |                                          |
#                      |<<_VirtualEVENT>>|                                          |
#                      |                 |                                          |
.bind(                  "<KeyPress-Left>", self.__doWidgetBoundTaskSpecificHANDLER  )
.bind_class( "Button",  "<KeyPress-Left>", self.__doClass_BoundTaskSpecificHANDLER  )
.bind_all(              "<KeyPress-Left>", self.__doApplicBoundTaskSpecificHANDLER  )

辞書で動くようにプログラムする方法

これはグリーンフィールドの問題であり、MVC-Model-Partで辞書の使用に制限されている場合は、そこに行きます。上記の問題の後、方向の有限状態オートマトン(FSA)(ブラインド状態遷移のトリガーの{ <KeyPress>| <KeyRelease>}ペアだけでなく、TimeDOMAIN近接処理と拡張されたキーのシーケンスに基づく)単一キーとデュアル・キーの押し状態文法{nilを、LeftUpRightDownLeft&&UpLeft&&DnRight&&UpRight&&Dn}とハンドリングは)少し複雑な成長しますが、最初のプロトタイプのために、あなただけの辞書割り当てルールを変更することができ、このような何かで始まります:

def on_keypress( event ):                          # keeping the Globals-style,
    global direction                               #         however shall be rather
    global x_vel                                   #         implemented in a Class-based
    global y_vel                                   #         manner

    direction     = dir_vel[event.keysym][0]       # ref. remark on more complex FSA
    x_vel        += dir_vel[event.keysym][1]
    y_vel        += dir_vel[event.keysym][2]

def on_keyrelease( event ):
    global direction
    global x_vel
    global y_vel
    x_vel        -= dir_vel[event.keysym][1]
    y_vel        -= dir_vel[event.keysym][2]
    if abs( x_vel * y_vel ) < 0.1:
        direction = None                          # ref. remark on more complex FSA

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ