Wiley.Mobile.Python.Rapid.prototyping.of.applications.on.the.mobile.platform.Dec.2007 (779889), страница 17
Текст из файла (страница 17)
Thecallback functions are called when the screen must be redrawn orwhen a keyboard event occurs. The redraw callback() functionis described in Section 5.3 and the event callback function inSections 5.2.2 and 5.2.3.Now, let’s dive into the three approaches on programming keyboardkeys.5.2.1 Binding a Keycode to a Callback FunctionIn this approach, we bind a callback function to respond to a specific keyevent.
The key is identified by a keycode. For each key on the keyboardthere exists at least one keycode that corresponds to a particular characteror action, as shown in Figure 5.3. Note that a single physical key mayproduce many different characters; thus, many different keycodes maycorrespond to a single key.The keycodes are defined as constants in the module key codes.You can find an overview of often used keycodes in Figure 5.3.
To use thekeycodes, you need to import the key codes module at the beginningof the script.Example 28: Binding a keycode to a callback functionimport appuifw, e32, key_codesdef up():appuifw.note(u"Up arrow was pressed")def two():appuifw.note(u"Key 2 was pressed")def quit():app_lock.signal()canvas = appuifw.Canvas()appuifw.app.body = canvascanvas.bind(key_codes.EKeyUpArrow, up)canvas.bind(key_codes.EKey2, two)appuifw.app.exit_key_handler = quitapp_lock = e32.Ao_lock()app_lock.wait()KEYBOARD KEYSKeycodes87Scancodes1EKeyLeftSoftkeyEScancodeLeftSoftkey2EKeyYesEScancodeMenu3EKeyStarEScancodeMenu4EKey5EScancode55EKeyStarEScancodeStar6EKeyLeftArrowEScancodeLeftArrow7EKeyUpArrowEScancodeUpArrow8EKeySelectEScancodeSelect9EKeyRightArrowEScancodeRightArrow10EkeyDownArrowEScancodeDownArrow11EKeyRightSoftkeyEScancodeRightSoftkey12EKeyNoEScancodeNo13EKeyBackspaceEScancodeBackspace14EKeyEditEScancodeEdit15EKeyHashEScancodeHashFigure 5.3 Overview of keycodes and scancodes88SOUND, INTERACTIVE GRAPHICS AND CAMERAThe canvas.bind() function binds a keycode to a callback function.For example, canvas.bind(key codes.EKeyUpArrow, up) bindsthe callback function up() to the up-arrow key.
This informs the canvasobject that whenever the key corresponding to the keycode EKeyUpArrow (navigation key up) is pressed, the callback function up() should becalled. Similarly, we bind the keycode EKey2 to the function two().In some cases, you may want to cancel the binding. This can beaccomplished by binding the value None to a keycode, in place of acallback function.5.2.2Using the event callback() FunctionIn the second approach, we use a single callback function named keys()to handle all key events. Depending on the parameter event that is givento the function, we take a corresponding action. We use the Canvasobject’s event callback parameter to direct all events to a singlefunction, keys().Example 29: Using the event callback() functionimport appuifw, key_codes, e32def keys(event):if event['keycode'] == key_codes.EKeyUpArrow:appuifw.note(u"Up arrow was pressed")elif event['keycode'] == key_codes.EKey2:appuifw.note(u"Key 2 was pressed")def quit():app_lock.signal()canvas = appuifw.Canvas(event_callback = keys)appuifw.app.body = canvasappuifw.app.exit_key_handler = quitapp_lock = e32.Ao_lock()app_lock.wait()When the user presses a key, the canvas receives a key event andgenerates a dictionary object which is handed to the keys() function through the parameter event.
This object holds information aboutthe key that produced the event and whether the key was pressed orreleased.In essence, a dictionary object is a collection of key–value pairs.This data structure might be familiar to you from other programminglanguages, such as Java’s Hashtable or PHP’s or Perl’s hash arrays.The dictionary object is introduced more thoroughly in Chapter 6 – hereKEYBOARD KEYS89we only peek inside the contents of one particular dictionary object,event.The event callback function receives a single parameter that is adictionary object, event. It includes the following information:•keycode is an identifier for the keyboard key event. Some physical keys on the keyboard may correspond to several keycodes, forinstance, to upper-case and lower-case A.
Thus, if your applicationmust recognize a specific character, keycodes are a suitable choice.Keycode names are defined in the key codes module and they startwith the letters EKey.• scancode is a lower-level identifier of the physical keyboard key.Scancode names start with the letters EScancode. If your applicationmust recognize events related to a physical key, scancodes are agood choice. See Figure 5.3 to see some cases where the keycodeand scancode do not map to the same key.
You can use scancodeswherever keycodes are used, for instance, you could have used themin Example 28.• modifiers returns modifier keys that apply to this key event, such asCtrl or Alt. Modifiers are seldom used on a mobile phone keyboard.• type indicates whether the key has just been pressed down(appuifw.EEventKeyDown), is down (appuifw.EEventKey), orhas been released (appuifw.EventKeyUp). We can use this information to distinguish between single clicks and continuous key presses(see Example 30).You can fetch the above values from the dictionary object as follows:ev_keycode = event["keycode"]ev_scancode = event["scancode"]ev_modifiers = event["modifiers"]ev_type = event["type"]To detect which key is being pressed, we simply compare the keycodeor scancode value from the event dictionary with the code that we wantto detect.
When the right softkey is pressed, the appuifw.app.exitkey handler() callback is always executed.5.2.3 Key Pressed or Held DownThe third approach shows how to distinguish whether a certain key wasclicked once or whether it is being held down. This can be useful, for90SOUND, INTERACTIVE GRAPHICS AND CAMERAinstance, in a game where a battleship is steered with arrow keys. In thiscase, being unable to see the distinction between a click that correspondsto a small adjustment and a continuous move to the right is likely to causea shipwreck.Example 30: Key pressed or held downimport appuifw, e32, key_codeskey_down = Noneclicked = Nonedef handle_event(event):global clicked, key_downif event["type"] == appuifw.EEventKey:if key_down:key_down = (event["keycode"], "down")else:key_down = (event["keycode"], "pressed")elif event["type"] == appuifw.EEventKeyUp and key_down:code, mode = key_downif mode == "pressed":clicked = codekey_down = Nonedef key_clicked(code):global clickedif code == clicked:clicked = Nonereturn Truereturn Falsedef key_is_down(code):if key_down and key_down == (code, "down"):return Truereturn Falsedef quit():global runningrunning = Falsecanvas = appuifw.Canvas(event_callback = handle_event)appuifw.app.body = canvasappuifw.app.exit_key_handler = quitrunning = Truewhile running:e32.ao_sleep(0.1)if key_clicked(key_codes.EKeyUpArrow):appuifw.note(u"Up arrow was pressed")elif key_is_down(key_codes.EKey2):canvas.clear((0, 0, 255))else:canvas.clear((255, 255, 255))This example is somewhat more complex than the previous ones.
Donot worry if you cannot understand this script instantly. You can alwaysKEYBOARD KEYS91come back to it later once you have advanced in the book and havelearned more about Python.This example uses an event callback function that is similar to thesecond approach. In contrast to the second approach, however, here weuse the event type in event["type"] to distinguish between the statesof a key.These event-handling functions are not application-specific, but areusable in any application. This is in contrast to both the previousapproaches, which included application-specific actions (showing thedialogs) in the event-handling function.
Because of this, you can use thefunctions handle event(), key clicked() and key is down()in your own applications.The event callback function handle event() works as follows: ifthe key is down (event type appuifw.EEventKey), we make a distinction between the first key-down event, when the variable key downequals None and further events that happen only if the key is not releasedimmediately. We mark the first event with "pressed" and the following key-down events with "down". When the key is released (eventtype appuifw.EEventKeyUp) we check the mode: if the key was"pressed", the user has only clicked the key and we save the keycodeto the variable clicked.
If the mode was "down", this event means thatthe key was just released and we reset the key down variable back toNone.Given a keycode, the function key clicked() checks whether thelast clicked key in the variable clicked equals the parameter and thenresets clicked. Thus, with this function you can check whether a certainkey was clicked.In a similar manner, we check whether the key that is now helddown (if any) equals the parameter in the function key is down().The function returns True as long as the particular key is held down.As with the previous approaches, a click of the up-arrow key shows adialog.
If you hold the key down, instead of just clicking it, no dialog isshown. On the other hand, if you hold the 2 key down, the screen turnsblue. However, if you just click the 2 key, nothing happens. We couldhave shown another dialog when the 2 key is held down, but seeingmany dialogs in a row saying that the key is still down would be ratherannoying.
That is why the screen is turned blue instead.Later on, we use this approach in a drawing program (Example 33).5.2.4 Capturing any Key Event on Your PhoneThe keycapture module offers an API for global capturing of keyevents. With this module, you can react to key events even if some otherS60 application is active and your PyS60 program is running only in thebackground.