Skip to the content.

Control: type

When the user types on her keyboard.

This control is sent when the user presses on a key (or on a combination of keys) on her keyboard that would lead to writing a character. Contrary to the press control, this one is highly tied to the user keyboard layout and the state of the Caps Lock key.

Assuming, for instance, the user is on an international QWERTY keyboard. If she presses the ‘ key, this control will not be fired (‘ being a dead key on international QWERTY). But if the user then presses on ‘e’, the “type” control will be sent with the typed key set to ‘é’.

In other words, this control is more useful to watch what user are typing rather than specific key presses on their keyboard. A type control is not sent each time a key is being pressed (as the example above demonstrated). Not all key presses will result in a character being typed (arrow keys, for instance, will not). If you don’t know which control to watch, read: choose between press and type.


The type control is somewhat similar in binding to the press control. Instead of specifying the key (or keys) being typed in the method name, you can directly place the character being typed:

def on_type_I(self, ...):

Notice: this method will only be called if the user types an uppercase ‘i’, that is, if she types the Shift key then the ‘i’ key, or the Caps Lock key and the ‘i’ key then. Contrary to press, character names in the method are case-sensitive.

You can use this control on a widget too. Assuming you want to react if the user types a ‘8’ while focusing on a list of ID “choices”:

def on_type_8_in_choices(self, ...):

Again, notice that contrary to press, typing a ‘8’ is not equivalent on all keyboard layouts. Some will need to press she Shift key to do it, some will not, some might access the digit with other modifier keys. And of course, this method will also be called if the Num Lock is on and the user presses the numpad8 key.

Sub-controls and main controls

As usual, a sub-control method always holds priority on a main control method:

def on_type(self, unicode):
    # Main control intercepting almost anything

def on_type_b(self):
    # sub-control

The second method will be called if the user types a ‘b’. The first method will be called if the user types anything but a ‘b’.

What keys to intercept?

As pointed out above, not all keys will lead to a character being typed. You can write unicode characters directly in your method name, thanks to Python 3’s unicode support in identifiers.

def on_type_é(self):

However, Python will not allow you to use all identifiers. Creating such a method will raise a SyntaxError:

def on_type_€(self):

So as a general rule, if you are in doubt about what to capture or think the character in question would cause an error, just use a main control and check the unicode key as shown below.

Obtain the key in the control method

Although it is possible to place the typed character in the method name as shown above, it is more common to create a main control method and check the unicode value. You can do so by specifying the unicode keyword argument in your control method:

def on_type(self, unicode):
    if unicode == "€":

Control attributes

The control object has the following attributes:

Attribute Type Note
unicode str The character being typed.

Use these attributes as your control method argument. For instance:

def on_type(self, unicode):

Alternatively you can specify the control keyword argument in your method signature which will always contain the control object.

def on_type(self, control):
    print(f"The user will type {control.unicode}.")