• Tkinter > les évènements

      1. LES TOUCHES

      Pour chaque widget, on peut écouter une événement avec un bind :

       

      monWidget.bind(event, handler)

       

      Si un événement event est entendu dans monWidget, alors on appelle une fonction handler.

       

      Exemple : écouter le clic gauche <Button-1> sur la Frame frame. A chaque clic, on exécute la fonction callback :

       

      from Tkinter import *
      root = Tk()
      
      def callback(event):
          print "Vous avez cliqué à ", event.x, event.y
      
      frame = Frame(root, width=100, height=100)
      frame.bind("<Button-1>", callback)
      frame.pack()
      
      root.mainloop()

       

      Les écoutes du clavier se font sur des éléments qui ont le focus. On utilise la méthode focus_set pour donner le focus à un élément :

       

      from Tkinter import *
      root = Tk()
      
      def key(event):
          print "pressed", repr(event.char)
      
      def callback(event):
          frame.focus_set()
          print "clicked at", event.x, event.y
      
      frame = Frame(root, width=100, height=100)
      frame.bind("<Key>", key)
      frame.bind("<Button-1>", callback)
      frame.pack()
      
      root.mainloop()

      Events

      <modifier-type-detail>

       

      Les évènements sont de type user (souris, clavier) ou window (Enter, Configure).

      There are also various ways to simplify the event string; for example, to match a keyboard key, you can leave out the angle brackets and just use the key as is. Unless it is a space or an angle bracket, of course.

      Instead of spending a few pages on discussing all the syntactic shortcuts, let’s take a look on the most common event formats:

      Event Formats

      <Button-1> clic gauche

      <Button-2> clic milieu

      <Button-3> clic droit

      La position de la souris est définie par x et y de l’objet event passé au callback.

       

      <B1-Motion> The mouse is moved, with mouse button 1 being held down (use B2 for the middle button, B3 for the right button). The current position of the mouse pointer is provided in the x and y members of the event object passed to the callback.

      <ButtonRelease-1> Button 1 was released. The current position of the mouse pointer is provided in the x and y members of the event object passed to the callback.

      <Double-Button-1> Button 1 was double clicked. You can use Double or Triple as prefixes. Note that if you bind to both a single click (<Button-1>) and a double click, both bindings will be called.

      <Enter> Lorsque la souris entre dans un widget (sans nécessairement avoir cliqué).

      <Leave> Lorsque la souris quitte le widget.

       

      <FocusIn> Keyboard focus was moved to this widget, or to a child of this widget.

      <FocusOut> Keyboard focus was moved from this widget to another widget.

       

      LES TOUCHES

      <Return> touche ENTREE - <Cancel>

      <BackSpace>, <Tab>,

      <Shift_L> (any Shift key) - <Control_L> (any Control key) - <Alt_L> (any Alt key),

      <Pause>,

      <Caps_Lock> -

      <Escape> -

      <Prior> (Page Up) -

      <Next> (Page Down) -

      <End> - <Home> -

      <Left> - <Up> - <Right> - <Down> -

      <Print>,

      <Insert>,

      <Delete>,

      <F1> à <F12> touches F1 à F12 - <Num_Lock> touche Verr Num - <Scroll_Lock> - touche Arrêt défil

      <Key> any key (provided in the char member of the event object passed to the callback (this is an empty string for special keys).

      a The user typed an “a”. Most printable characters can be used as is.

      <space>

      <less>

      Note that 1 is a keyboard binding, while <1> is a button binding.

      <Shift-Up> The user pressed the Up arrow, while holding the Shift key pressed. You can use prefixes like Alt, Shift, and Control.

       

      <Configure> Lorsque le widget a changé de taille (ou d’espace ou de plateforme). La nouvelle taille est récupérée avec width et height attributes of the event object passed to the callback.

      Event Attributes

      widgetThe widget which generated this event. This is a valid Tkinter widget instance, not a name. This attribute is set for all events.

      x, y The current mouse position, in pixels.

      x_root, y_root The current mouse position relative to the upper left corner of the screen, in pixels.

      char The character code (keyboard events only), as a string.

      keysym The key symbol (keyboard events only).

      keycode The key code (keyboard events only).

      num The button number (mouse button events only).

      width, height The new size of the widget, in pixels (Configure events only).

      type The event type.

      For portability reasons, you should stick to char, height, width, x, y, x_root, y_root, and widget. Unless you know exactly what you’re doing, of course…

      Instance and Class Bindings

      The bind method we used in the above example creates an instance binding. This means that the binding applies to a single widget only; if you create new frames, they will not inherit the bindings.

      But Tkinter also allows you to create bindings on the class and application level; in fact, you can create bindings on four different levels:

    • the widget instance, using bind.
    • the widget’s toplevel window (Toplevel or root), also using bind.
    • the widget class, using bind_class (this is used by Tkinter to provide standard bindings).
    • the whole application, using bind_all.
    • For example, you can use bind_all to create a binding for the F1 key, so you can provide help everywhere in the application. But what happens if you create multiple bindings for the same key, or provide overlapping bindings?

       

      First, on each of these four levels, Tkinter chooses the “closest match” of the available bindings. For example, if you create instance bindings for the <Key> and <Return> events, only the second binding will be called if you press the Enter key.

      However, if you add a <Return> binding to the toplevel widget, both bindings will be called. Tkinter first calls the best binding on the instance level, then the best binding on the toplevel window level, then the best binding on the class level (which is often a standard binding), and finally the best available binding on the application level. So in an extreme case, a single event may call four event handlers.

      A common cause of confusion is when you try to use bindings to override the default behavior of a standard widget. For example, assume you wish to disable the Enter key in the text widget, so that the users cannot insert newlines into the text. Maybe the following will do the trick?

       

      def ignore(event):
          pass
      text.bind("<Return>", ignore)

       

      or, if you prefer one-liners:

       

      text.bind("<Return>", lambda e: None)

       

      (the lambda function used here takes one argument, and returns None)

      Unfortunately, the newline is still inserted, since the above binding applies to the instance level only, and the standard behavior is provided by a class level bindings.

      You could use the bind_class method to modify the bindings on the class level, but that would change the behavior of all text widgets in the application. An easier solution is to prevent Tkinter from propagating the event to other handlers; just return the string “break” from your event handler:

       

      def ignore(event):
          return "break"
      text.bind("<Return>", ignore)

      or

      text.bind("<Return>", lambda e: "break")

       

      By the way, if you really want to change the behavior of all text widgets in your application, here’s how to use the bind_class method:

       

      top.bind_class("Text", "<Return>", lambda e: None)

       

      But there are a lot of reasons why you shouldn’t do this. For example, it messes things up completely the day you wish to extend your application with some cool little UI component you downloaded from the net. Better use your own Text widget specialization, and keep Tkinter’s default bindings intact:

       

      class MyText(Text):
          def __init__(self, master, **kw):
              apply(Text.__init__, (self, master), kw)
              self.bind("<Return>", lambda e: "break")

      Protocols #

      In addition to event bindings, Tkinter also supports a mechanism called protocol handlers. Here, the term protocol refers to the interaction between the application and the window manager. The most commonly used protocol is called WM_DELETE_WINDOW, and is used to define what happens when the user explicitly closes a window using the window manager.

      You can use the protocol method to install a handler for this protocol (the widget must be a root or Toplevel widget):

      widget.protocol("WM_DELETE_WINDOW", handler)

      Once you have installed your own handler, Tkinter will no longer automatically close the window. Instead, you could for example display a message box asking the user if the current data should be saved, or in some cases, simply ignore the request. To close the window from this handler, simply call the destroy method of the window:

       

      Capturing destroy events


      from Tkinter import *
      import tkMessageBox
      
      def callback():
          if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
              root.destroy()
      
      root = Tk()
      root.protocol("WM_DELETE_WINDOW", callback)
      
      root.mainloop()

       

      Note that even you don’t register an handler for WM_DELETE_WINDOW on a toplevel window, the window itself will be destroyed as usual (in a controlled fashion, unlike X). However, as of Python 1.5.2, Tkinter will not destroy the corresponding widget instance hierarchy, so it is a good idea to always register a handler yourself:

       

      top = Toplevel(...)
      
      # make sure widget instances are deleted
      top.protocol("WM_DELETE_WINDOW", top.destroy)

       

      Future versions of Tkinter will most likely do this by default.

      Other Protocols

      WM_TAKE_FOCUS and WM_SAVE_YOURSELF

      Définition de bindings

      Exemple : deux fonctions pour afficher «hello world!» et pour afficher «bye» sur la sortie standard avant de quitter le programme. Ensuite, il crée un label et y associe la fonction hello au clic gauche et la fonction quit au double clic.

      >>> import Tkinter
      >>> import sys
      >>> def hello(event):
      ...     print 'hello world!'
      ...
      >>> def quit(event):
      ...     print 'bye'
      ...     sys.exit()
      ...
      >>> widget = Tkinter.Label(None, text='press')
      >>> widget.pack()
      >>> widget.bind('<Button-1>', hello)
      '805810704hello'
      >>> widget.bind('<Double-1>', quit)
      
      >>> widget.mainloop()

      L’événement «reçu» par un handler contient des informations qui peuvent être interprétées dans le cadre du traitement. L’exemple suivant définit deux fonctions dont le but est d’afficher un caractère tapé au clavier et d’afficher les coordonnées de la souris. La classe Tk représente la fenêtre principale du programme. Le label créé est associé à cette fenêtre (premier paramètre du constructeur). Puis, les deux fonctions sont associées au clavier et au clic sur le label. L’utilisation de focus sélectionne le label pour recevoir les événements clavier. Enfin, la boucle d’événements est démarré sur la fenêtre principale. Lorsque la fenêtre est active et que l’on tape une touche au clavier, cela génère un événement passé à la fonction onKey qui va en extraire le caractère associé. (Même principe pour le clic de souris.)

      import Tkinter
      def onKey(event):
          print 'got key', event.char
      def onClick(event):
          print event.widget, event.x, event.y
      
      root = Tkinter.Tk()
      lab = Tkinter.Label(root, text='hello world')
      lab.bind('<KeyPress>', onKey)
      lab.bind('<Button-1>', onClick)
      lab.focus()
      lab.pack()
      root.mainloop()
      .805789368 30 14
      .805789368 44 11
      got key e
      got key r

      Quelques noms de bindings courants

      <KeyPress> Pression sur une touche

      <KeyPress-a> Pression sur la touche ‘A’ (minuscule)

      <KeyPress-A> Pression sur la touche ‘A’ (majuscule)

      <Return> Pression sur entrée

      <Escape> Touche d’échappement

      <Up> <Down> Pression sur les flèches

      <Button-1> click souris gauche

      <Button-2> Click souris milieu (ou les deux)

      <Button-3> Click souris droit

      <ButtonRelease> Fin de click gauche

      <Motion> Mouvement de la souris

      <B1-Motion> Mouvement de la souris avec click gauche

      <Enter> <Leave> Entrée et sortie souris d’un widget

      <Configure> Redimensionnement de la fenêtre

      <Map> <Unmap> Ouverture et iconification de la fenêtre

 

Aucun commentaire

 

Laissez un commentaire