How Can I Program Two Simultaneous Key Press Events In Tkinter To Move A Canvas Item Diagonally Using A Dictionary Of Keypress Events?
Solution 1:
How can I program ... events
Program part: Tkinter can, on it's own, generate UI-event, without an external stimulus actually happening "in front" of the UI. So, "How can I program an event" part is done with this method:
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 )
Problems with Simultaneity:
As a principle, Tkinter / Python code is being executed sequentially. There is no simple way how to instantiate two events at the very same moment. Simply put, your code has to somehow mimic/detect the near-simultaneous events, because it is by nature a sequential processor.
As Bryan Oakley has well explained in some other post, the UI-detection shall bear in mind, that holding an ArrowUp and/or ArrowLeft may lead in reality into auto-generated sequence of UI-*events, outside of one's control ( old days with BIOS keyboard typematic rate setting, responsible for auto-repeating the key-stroke once a keyboard detects a key is held pressed ... are not over ... )
How to read the input-stimuli
Tkinter has a powerful set of MVC-Controller-Part methods for handling ( both naturally UI-detected and artificially "injected" by .event_generate()
) events. That will be important for other aspects of the task:
# 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
For detecting such events, Tkinter is equipped with these methods:
# |<<_aNamedEVENT_>>|<<______________________________aHANDLER>>|
# |or | |
# |<<_VirtualEVENT>>| |
# | | |
.bind( "<KeyPress-Left>", self.__doWidgetBoundTaskSpecificHANDLER )
.bind_class( "Button", "<KeyPress-Left>", self.__doClass_BoundTaskSpecificHANDLER )
.bind_all( "<KeyPress-Left>", self.__doApplicBoundTaskSpecificHANDLER )
How to program to move with dictionary
This is a green-field issue and if restricted to use a dictionary in MVC-Model-Part, there you go. After issues above, your Finite-State-Automaton (FSA) for direction ( based on not only a { <KeyPress>
| <KeyRelease>
} pair of a blind state-transitions' triggers, but on sequence of keys, with a TimeDOMAIN proximity handling and with an extended, single-key and dual-key-pressed state grammar { nil, Left, Up, Right, Down, Left&&
Up, Left&&
Dn, Right&&
Up, Right&&
Dn } and handling ) grows a bit complex, but for a first prototype, you may just change the dictionary assignment rules and start with something like this:
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
Solution 2:
I was just playing around with simultaneous keypresses and it turns out they're up to 10 ms apart, so if you check that two buttons are pressed within 20 ms of each other, you can consider them simultaneous. I'm sure there's a more elegant solution though.
Post a Comment for "How Can I Program Two Simultaneous Key Press Events In Tkinter To Move A Canvas Item Diagonally Using A Dictionary Of Keypress Events?"