Vous êtes sur la page 1sur 203

Traduit de Anglais vers Français - www.onlinedoctranslator.

com

Documentation Kivy
Version 2.1.0.dev0

Les développeurs Kivy

08 octobre 2021
CONTENU

je Projet Kivy 3
1 Philosophie 5

2 Contribuant sept

3 FAQ 23

4 Nous contacter 29

II Guide de programmation 31
5 Les bases de Kivy 33

6 Contrôler l'environnement 39

sept
Configurer Kivy 43

8 Aperçu architectural 45

9 Événements et propriétés 49

10 Gestion des entrées 59

11 widgets 67

12 graphiques 87

Langue 13Kv 89

14 Intégration avec d'autres frameworks 101

15 Emballage de votre demande 105

16 Licences de package 123

III Tutoriels 127


Tutoriel du jeu 17 Pong 129

18 Une application de peinture simple 143

19 Cours accéléré 153

je
IV Référence de l'API 155
Cadre 20 Kivy 157

21 abstraction de base 265

22 Module Kivy pour les dépendances binaires. 301

23 effets 303

24 Jardin 309

25 graphiques 313

26 Gestion des entrées 391

27 Langue Kivy 415

28 Bibliothèques externes 437

29 modules 441

30 Assistance réseau 453

31 Stockage 457

32 outils 463

33 widgets 465

V Annexe 715
34 Permis 717

Index des modules Python 719

Indice 721

je
Bienvenue dans la documentation de Kivy. Kivy est une bibliothèque de logiciels open source pour le développement rapide
d'applications équipées de nouvelles interfaces utilisateur, telles que les applications multi-touch.

Nous vous recommandons de commencer par Commencer. Dirigez-vous ensuite vers leGuide de programmation. Nous avons
égalementCréer une candidature si vous êtes impatient.

Vous vous demandez probablement pourquoi vous devriez être intéressé par l'utilisation de Kivy. Il existe un document
décrivant notrePhilosophie que nous vous encourageons à lire, et un Aperçu architectural.

Si vous souhaitez contribuer à Kivy, assurez-vous de lire Contribuant. Si votre problème n'est pas traité dans la
documentation, n'hésitez pas àNous contacter.

1
2
Partie I

PROJET KIVY

Cette partie de la documentation explique les idées de base derrière la conception de Kivy et pourquoi vous voudriez l'utiliser.

3
4
CHAPITRE

UN

PHILOSOPHIE

Si vous vous demandez en quoi consiste Kivy et ce qui le distingue des autres solutions, ce document
est pour vous.

1.1 Pourquoi s'embêter ?

Pourquoi voudriez-vous utiliser Kivy? Après tout, il existe de nombreuses boîtes à outils (ou frameworks, ou plates-
formes) intéressantes - gratuitement. Vous avez Qt et Flash, pour ne citer que deux bons choix pour le développement
d'applications. Beaucoup de ces nombreuses solutions prennent déjà en charge Multi-Touch, alors qu'est-ce qui rend
Kivy spécial et intéressant à utiliser ?

1.1.1 Frais

Kivy est fait pour aujourd'hui et pour demain. Les nouvelles méthodes de saisie telles que Multi-Touch sont devenues de plus en
plus importantes. Nous avons créé Kivy à partir de zéro, spécifiquement pour ce type d'interaction. Cela signifie que nous avons
pu repenser beaucoup de choses en termes d'interaction homme-machine, alors que les boîtes à outils plus anciennes (pour ne
pas dire « obsolètes », plutôt « bien établies ») portent leur héritage, qui est souvent un fardeau. Nous n'essayons pas de forcer
cette nouvelle approche de l'utilisation d'un ordinateur dans le corset des modèles existants (disons l'interaction d'un seul
pointeur avec la souris). Nous voulons le laisser s'épanouir et vous laisser explorer les possibilités.Cette est ce qui distingue
vraiment Kivy.

1.1.2 Rapide

Kivy est rapide. Ceci s'applique aux deuxdéveloppement d'applications et exécution de l'application vitesses. Nous avons
optimisé Kivy de plusieurs manières. Nous implémentons des fonctionnalités urgentes sur leniveau C pour tirer parti de la
puissance des compilateurs existants. Plus important encore, nous utilisons égalementalgorithmes intelligents pour minimiser
les opérations coûteuses. Nous utilisons également leGPU partout où cela a du sens dans notre contexte. La puissance de calcul
des cartes graphiques d'aujourd'hui dépasse de loin celle des processeurs d'aujourd'hui pour certaines tâches et algorithmes,
en particulier le dessin. C'est pourquoi nous essayons de laisser le GPU faire le plus de travail possible, augmentant ainsi
considérablement les performances.

5
1.1.3 Souple

Kivy est flexible. Cela signifie qu'il peut être exécuté surune variété d'appareils différents, y compris les smartphones et tablettes
Android. Nous soutenonstous les principaux systèmes d'exploitation (Windows, Linux, OS X). Être flexible signifie également que
le développement rapide de Kivy lui permet des'adapter rapidement aux nouvelles technologies. Plus d'une fois, nous avons
ajouté la prise en charge de nouveaux périphériques externes et protocoles logiciels, parfois même avant leur sortie. Enfin, Kivy
est également flexible dans la mesure où il est possible de l'utiliser en combinaison avec un grand nombre de solutions tierces
différentes. Par exemple, sous Windows, nous prenons en charge WM_TOUCH, ce qui signifie que tout appareil doté des pilotes
Windows 7 Pen & Touchjuste travailler avec Kivy. Sur OS X, vous pouvez utiliser les appareils compatibles Multi-Touch d'Apple,
tels que les trackpads et les souris. Sous Linux, vous pouvez utiliser les événements d'entrée du noyau HID. En plus de cela, nous
prenons en charge TUIO (Tangible User Interface Objects) et un certain nombre d'autres sources d'entrée.

1.1.4 Concentré

Kivy est concentré. Vous pouvez écrire une application simple avec quelques lignes de code. Les programmes Kivy sont créés en
utilisant lePython langage de programmation, qui est incroyablement polyvalent et puissant, mais facile à utiliser. De plus, nous
avons créé notre propre langage de description, leLangue Kivy, pour créer des interfaces utilisateur sophistiquées. Ce langage
vous permet de paramétrer, connecter et organiser rapidement les éléments de votre application. Nous pensons que vous
permettre de vous concentrer sur l'essence de votre application est plus important que de vous forcer à modifier les paramètres
du compilateur. Nous avons enlevé ce fardeau de vos épaules.

1.1.5 Financé

Kivy est activement développé par des professionnels dans leur domaine. Kivy est une solution influencée par la communauté,
développée par des professionnels et soutenue commercialement. Certains de nos principaux développeurs développent Kivy pour
gagner leur vie. Kivy est là pour rester. Ce n'est pas un petit projet étudiant en voie de disparition.

1.1.6 Gratuit

Kivy est libre d'utilisation. Vous n'avez pas à payer pour cela. Vous n'avez même pas à payer pour cela si vous gagnez de
l'argent en vendant une application qui utilise Kivy.

6
CHAPITRE

DEUX

CONTRIBUANT

Il existe de nombreuses façons de contribuer à Kivy. Les correctifs de code ne sont qu'une chose parmi d'autres que vous pouvez
soumettre pour aider le projet. Nous accueillons également les commentaires, les rapports de bogues, les demandes de fonctionnalités,
les améliorations de la documentation, la publicité et le plaidoyer, les tests, les contributions graphiques et bien d'autres idées. Parlez-
nous simplement si vous voulez aider, et nous vous aiderons à nous aider.

2.1 Débats

Les discussions autour du développement de Kivy ont lieu sur les problèmes de Github et les demandes d'extraction pour des choses
spécifiques. Pour les choses qui ne rentrent pas dans l'un ou l'autre, des discussions ont lieu sur le#dev Chaîne Discord, et sur le groupe
google kivy-dev. N'hésitez pas à venir demander conseil si vous n'êtes pas sûr de la manière de contribuer, ou si vous souhaitez avoir la
confirmation que vos idées s'intègrent dans le projet avant de travailler dessus. Si vous souhaitez demander - ou contribuer - un soutien,
vous pouvez rejoindre le#supporter la chaîne Discord, et le groupe google des utilisateurs de kivy.

2.2 Code de conduite

Dans l'intérêt de favoriser une communauté ouverte et accueillante, nous, en tant que contributeurs et mainteneurs, devons
nous assurer que la participation à notre projet et à nos projets frères est une expérience positive et sans harcèlement pour tout
le monde.

En tant que tel, il est essentiel que toutes les interactions soient menées d'une manière véhiculant le respect, l'ouverture d'esprit
et la gratitude. Pour une discussion plus complète de ces lignes directrices, veuillez vous référer auEngagement des
contributeurs. Ce document fournit une description précise de ce que l'on attend de vous, à la fois en tant que développeur
principal ou en tant que contributeur débutant.

2.3 Commentaires

C'est de loin le moyen le plus simple de contribuer à quelque chose. Si vous utilisez Kivy pour votre propre projet, n'hésitez pas à
partager. Il n'est évidemment pas nécessaire que ce soit une application d'entreprise haut de gamme. C'est juste
incroyablement motivant de savoir que les gens utilisent les choses que vous développez et ce que cela leur permet de faire. Si
vous avez quelque chose à nous dire, n'hésitez pas. Les captures d'écran et les vidéos sont également les bienvenues ! Nous
nous intéressons également aux problèmes que vous avez rencontrés au démarrage. N'hésitez pas à signaler tous les obstacles
que vous avez rencontrés, tels que des documents manquants, des instructions trompeuses ou similaires. Nous sommes
perfectionnistes, donc même si ce n'est qu'une faute de frappe, faites-le nous savoir.

sept
2.4 Signaler un problème

Si vous avez trouvé quelque chose qui ne va pas, un plantage, une erreur de segmentation, une documentation manquante, une orthographe incorrecte ou simplement des

exemples étranges, veuillez prendre 2 minutes pour signaler le problème.

1. Déplacez votre niveau de journalisation vers le débogage en éditant <répertoire_utilisateur>/.kivy/config.ini:

[kivy]
log_level = déboguer

2. Exécutez à nouveau votre code et copiez/collez la sortie complète dans http://gist.github.com/, y


compris le journal de Kivy et le backtrace python.

3. Ouvrir https://github.com/kivy/kivy/issues/
4. Définissez le titre de votre problème

5. Expliquez exactement ce qu'il faut faire pour reproduire le problème et collez le lien de la sortie publiée sur
http://gist.github.com/

6. Validez le problème et le tour est joué !

Si vous vous sentez à la hauteur, vous pouvez également essayer de résoudre le bogue et contribuer en nous envoyant le patch :) Lisez la
section suivante pour savoir comment procéder.

2.5 Cotisations des codes

Les contributions au code (patchs, nouvelles fonctionnalités) sont le moyen le plus évident d'aider au développement du projet. Étant
donné que cela est si courant, nous vous demandons de suivre notre flux de travail pour travailler le plus efficacement possible avec
nous. Le respect de notre flux de travail garantit que votre contribution ne sera pas oubliée ou perdue. De plus, votre nom sera toujours
associé au changement que vous avez effectué, ce qui signifie essentiellement une renommée éternelle dans notre histoire de code (vous
pouvez vous désinscrire si vous ne le souhaitez pas).

2.5.1 Style de codage

• Si vous ne l'avez pas encore fait, lisez le PEP8 sur le style de codage en python.

• Activez le pep8 et d'autres vérifications de base sur les commits git comme ceci :

faire un crochet

Cela transmettra le code ajouté à la zone de staging git (sur le point d'être validé) via un programme de vérification lorsque vous
effectuez une validation, et garantira que vous n'avez pas introduit d'erreurs de style. Si vous l'avez fait, le commit sera rejeté :
veuillez corriger les erreurs et réessayer.

Le vérificateur utilisé est pré-engager. Si vous devez ignorer une vérification particulière, consultezDocumentation, TLDR
étant ce qui met SKIP=nom du crochet devant de git commit sautera ce crochet, le nom du crochet incriminé est affiché
lorsqu'il échoue.

8
2.5.2 Performances

• s'occuper des problèmes de performance : lire Conseils de performances Python

• Les parties gourmandes en CPU de Kivy sont écrites en cython : si vous faites beaucoup de calculs, pensez à
l'utiliser aussi.

2.5.3 Git et GitHub

Nous utilisons git comme système de contrôle de version pour notre base de code. Si vous n'avez jamais utilisé git ou un DVCS
similaire (ou même n'importe quel VCS) auparavant, nous vous suggérons fortement de jeter un œil à l'excellente
documentation disponible pour git en ligne. leLivre de la communauté Git ou la Vidéos Git sont deux excellents moyens
d'apprendre git. Faites-nous confiance lorsque nous disons que git est un excellent outil. Cela peut sembler intimidant au début,
mais après un certain temps, vous l'aimerez (espérons-le) autant que nous. Cependant, vous enseigner git dépasse largement le
cadre de ce document.

Aussi, nous utilisons GitHub pour héberger notre code. Dans ce qui suit, nous supposerons que vous disposez d'un compte
GitHub (gratuit). Bien que cette partie soit facultative, elle permet une intégration étroite entre vos correctifs et notre base de
code en amont. Si vous ne souhaitez pas utiliser GitHub, nous supposons que vous savez de toute façon ce que vous faites.

2.5.4 Flux de travail du code

Voici donc la configuration initiale pour commencer avec notre flux de travail (vous n'avez besoin de le faire qu'une seule fois pour
installer Kivy). En gros, vous suivez les instructions d'installation deInstallation de développement, mais vous ne clonez pas notre
référentiel, vous le forkez. Voici les étapes :

1. Connectez-vous à GitHub

2. Créez une fourchette de Référentiel Kivy en cliquant sur le fourchette bouton.

3. Clonez votre fork de notre référentiel sur votre ordinateur. Votre fork aura le nom de télécommande git
'origin' et vous serez sur la branche 'master' :

git clone https://github.com/Nom d'utilisateur/kivy.idiot

4. Compilez et configurez PYTHONPATH ou installez (voir Installation de développement).

5. Installez notre hook de pré-commit qui garantit que votre code ne viole pas notre guide de style en exécutant faire un crochet
depuis le répertoire racine de votre clone. Cela exécutera notre vérification du guide de style chaque fois que vous effectuerez un
commit, et s'il y a des violations dans les parties que vous avez modifiées, votre commit sera abandonné. Corrigez et réessayez.

6. Ajoutez le référentiel kivy en tant que source distante :

git remote ajouter kivy https://github.com/kivy/kivy.idiot

Désormais, chaque fois que vous souhaitez créer un patch, vous suivez les étapes suivantes :

1. Vérifiez s'il existe un ticket dans notre outil de suivi des bogues pour le correctif ou la fonctionnalité et annoncez que
vous y travaillerez s'il n'a pas encore de responsable.

2. Créez une nouvelle branche nommée de manière appropriée dans votre référentiel local pour cette fonctionnalité ou
correction de bogue spécifique. (Garder une nouvelle branche par fonctionnalité garantit que nous pouvons
facilement extraire vos modifications sans extraire d'autres éléments qui ne sont pas censés être extraits.):

git caisse -b nouvelle_fonctionnalité

3. Modifiez le code pour faire ce que vous voulez (par exemple, corrigez-le).

9
4. Testez le code. Essayez de le faire même pour de petites corrections. Vous ne savez jamais si
vous avez introduit un bug étrange sans tester.

5. Effectuez un ou plusieurs commits atomiques minimaux par correctif ou par fonctionnalité. Moyenne minimale/
atomiquegarder le commit propre. Ne validez pas d'autres éléments qui n'appartiennent pas logiquement à ce
correctif ou à cette fonctionnalité. C'estne pas sur la création d'un commit par ligne modifiée. Utilisergit ajouter -p
si nécessaire.

6. Donnez à chaque commit un message de commit approprié, afin que les autres qui ne sont pas familiers
avec le sujet aient une bonne idée de ce que vous avez changé.

7. Une fois que vous êtes satisfait de vos modifications, extrayez notre référentiel en amont et fusionnez-le avec
votre référentiel local. Nous pouvons extraire vos données, mais puisque vous savez exactement ce qui a
changé, vous devez effectuer la fusion :

git pull maître de kivy

8. Poussez votre branche locale dans votre référentiel distant sur GitHub :

git push origin new_feature

9. Envoyez un Demande de tirage avec une description de ce que vous avez modifié via le bouton dans
l'interface GitHub de votre référentiel. (C'est pourquoi nous avons initialement forké. Votre référentiel est lié
au nôtre.)

Avertissement: Si vous modifiez des parties de la base de code qui nécessitent une compilation, vous
devrez recompiler pour que vos modifications prennent effet. leFabriquer La commande le fera pour
vous (voir le Makefile si vous voulez savoir ce qu'il fait). Si vous devez nettoyer votre répertoire actuel
des fichiers compilés, exécutezrendre propre. Si vous voulez vous débarrasser tout fichiers qui ne sont
pas sous contrôle de version, exécutez faire distclean (Mise en garde: Si vos modifications ne sont pas
sous contrôle de version, cette commande les supprimera !)

Nous allons maintenant recevoir votre pull request. Nous vérifierons si vos modifications sont propres et logiques (si
vous nous en avez parlé avant de faire tout cela, nous vous aurons dit si cela a du sens ou non). Si c'est le cas, nous les
tirerons et vous obtiendrez un karma instantané. Félicitations, vous êtes un héros !

2.6 Contributions documentaires

Les contributions de documentation suivent généralement le même workflow que les contributions de code, mais sont juste un peu plus
laxistes.

1. En suivant les instructions ci-dessus,

1. Forkez le référentiel.

2. Clonez votre fork sur votre ordinateur.

3. Configurez kivy repo en tant que source distante.

2. Installez python-sphinx. (Voirdocs/LISEZ-MOI à l'aide.)


3. Utilisez ReStructuredText_Markup pour apporter des modifications à la documentation HTML dans docs/sources.

Pour soumettre une mise à jour de la documentation, procédez comme suit :

1. Créez une nouvelle branche nommée de manière appropriée dans votre référentiel local :

git caisse -b my_docs_update

dix
2. Modifiez la documentation avec votre correction ou amélioration.

3. Regénérez les pages HTML et vérifiez votre mise à jour :

faire du html

4. Donnez à chaque commit un message de commit approprié, afin que les autres qui ne sont pas familiers avec le sujet
aient une bonne idée de ce que vous avez changé.

5. Gardez chaque commit concentré sur un seul thème connexe. Ne commitez pas d'autres choses qui n'appartiennent pas
logiquement à cette mise à jour.

6. Poussez vers votre référentiel distant sur GitHub :

git pousser

7. Envoyez un Demande de tirage avec une description de ce que vous avez modifié via le bouton dans l'interface GitHub de
votre référentiel.

Nous ne vous demandons pas de vous embêter à corriger une seule faute de frappe, mais pour des contributions plus
complexes, veuillez suivre le flux de travail suggéré.

2.6.1 Docstrings

Chaque module/classe/méthode/fonction a besoin d'une chaîne de documentation, utilisez donc les mots-clés suivants le cas échéant :

•.. version ajoutée :: pour marquer la version dans laquelle la fonctionnalité a été ajoutée.

•.. version changée :: pour marquer la version dans laquelle le comportement de la fonction a été modifié.

•.. Remarque:: pour ajouter des informations supplémentaires sur l'utilisation de la fonctionnalité ou de la fonctionnalité associée.

•.. avertissement:: pour indiquer un problème potentiel que l'utilisateur pourrait rencontrer en utilisant la fonctionnalité.

Exemples:

déf ma_nouvelle_fonctionnalité(soi, argument):


"""
La nouvelle fonctionnalité est géniale

. . version ajoutée :: 1.1.4

. . Remarque : Cette nouvelle fonctionnalité vous épatera probablement

. . attention :: Veuillez vous asseoir avant d'essayer cette fonctionnalité


"""

Aura pour résultat:

def my_new_feature(self, arg): La nouvelle fonctionnalité est géniale

Nouveau dans la version 1.1.4.

Noter: Cette nouvelle fonctionnalité va probablement vous épater

Avertissement: Veuillez vous asseoir avant d'essayer cette fonctionnalité

11
Lorsque vous faites référence à d'autres parties de l'API, utilisez :

• :mod:`~kivy.module` se référer à un module


• :classe :`~kivy.module.Class` se référer à une classe
• :meth:`~kivy.module.Class.method` se référer à une méthode
• :doc:`api-kivy.module` se référer à la documentation d'un module (idem pour une classe et une
méthode)

Remplacer évidemment classe de module et méthode avec leur vrai nom et en utilisant '.' pour séparer des modules se
référant à des modules imbriqués, par exemple :

:mod:`~kivy.uix.floatlayout` :class:`~kivy.uix.floatlayout.FloatLayout` :meth:`~kivy.core.window.WindowBase.toggle_full


api-kivy.core. fenêtre`

Aura pour résultat:

floatlayout FloatLayout toggle_fullscreen() Fenêtre


:doc: et :mode : sont essentiellement les mêmes, à l'exception d'une ancre dans l'URL qui rend :doc : préféré pour l'url du
nettoyeur.

Pour créer votre documentation, exécutez :

faire du html

Si vous avez mis à jour votre installation de Kivy et que vous rencontrez des problèmes pour compiler des documents, exécutez :

faire propre force html

Les documents seront générés dans docs/build/html. Pour plus d'informations sur le formatage docstring, veuillez vous
référer à la page officielle Documentation Sphinx.

2.7 Contributions des tests unitaires

Pour l'équipe de test, nous avons le document Tests unitaires qui explique comment fonctionnent les tests unitaires Kivy et comment
vous pouvez créer les vôtres. Utiliser la même approche que leFlux de travail de code soumettre de nouveaux tests.

2.7.1 Tests unitaires

Les tests sont situés dans le kivy/tests dossier. Si vous trouvez un bogue dans Kivy, une bonne chose à faire peut être d'écrire un
cas minimal montrant le problème et de demander aux développeurs principaux si le comportement affiché est voulu ou un vrai
bogue. Si vous écrivez votre code en tant queTest de l'unité , cela empêchera le bug de revenir inaperçu à l'avenir et fera de Kivy
un projet meilleur et plus fort. Écrire un test unitaire peut être un très bon moyen de se familiariser avec Kivy tout en faisant
quelque chose d'utile.

Les tests unitaires sont séparés en deux cas :

• Tests unitaires non graphiques : ce sont des tests unitaires standards qui peuvent s'exécuter dans une console

• Tests unitaires graphiques : ils nécessitent un contexte GL et, si demandé, fonctionnent via la comparaison d'images

Pour pouvoir exécuter des tests unitaires, vous devez installer pytest (https://pytest.org/) et la couverture (http://
nedbatchelder.com/code/coverage/). Vous pouvez utiliser pip pour cela :

12
sudo pip installer la couverture pytest

Ensuite, dans le répertoire kivy :

faire un test

Comment ça fonctionne

Tous les tests sont situés dans kivy/tests, et le nom du fichier commence par test_<nom>.py. Pytest rassemblera
automatiquement tous les fichiers et classes dans ce dossier et les utilisera pour générer des cas de test.

Pour écrire un test, créez un fichier qui respecte la dénomination précédente, puis commencez par ce modèle :

importer Test de l'unité

classer XXXTestCase(Test de l'unité.Cas de test):

déf mettre en place(soi):


# importer la classe et tout préparer ici. passe

déf test_AAAA(soi):
# placez votre cas de test ici une =
1
soi.affirmerÉgal(une, 1)

Remplacer XXX par un nom approprié qui couvre vos cas de test, puis remplacez « YYY » par le nom de votre test.
Si vous avez des doutes, vérifiez comment les autres tests ont été rédigés.

Ensuite, pour les exécuter, exécutez simplement :

faire un test

Si vous souhaitez exécuter ce fichier uniquement, vous pouvez exécuter :

pytest kivy/essais/test_votretestcase.py

ou inclure ce simple unittest.main() appeler à la fin du fichier et lancer le test avec python
test_yourtestcase.py:

si __Nom__ == '__principale__':
Test de l'unité.principale()

Tests unitaires graphiques

Alors que les tests unitaires simples sont parfaits et utiles pour garder les choses granulaires, dans certains cas, nous
devons tester Kivy après la création de la fenêtre GL pour interagir avec les graphiques, les widgets et tester des
éléments plus avancés tels que les widgets, les modules, divers cas d'entrée et l'interaction avec tout ce qui ne devient
disponible qu'une fois la fenêtre créée et Kivy correctement initialisé.

Ces tests sont exécutés de la même manière que les tests unitaires ordinaires, c'est-à-dire avec pytest ou via
unittest.main().

Voici deux exemples similaires avec différentes approches d'exécution de l'application. Dans le premier, vous configurez
les éléments requis manuellement et ledémolir() du Test d'unité graphique ne peut essayer de le nettoyer qu'après
avoir :

13
à partir de kivy.tests.common importer Test d'unité graphique

classer MonTestCase(Test d'unité graphique):

déf test_runtouchapp(soi):
# approche non intégrée à partir de kivy.app
importer exécuterTouchApp à partir de bouton
kivy.uix importer Bouton

bouton = Bouton()
exécuterTouchApp(bouton)

# récupérez votre instance Window en toute


sécurité à partir de kivy.base importer EventLoop
EventLoop.assurer_fenêtre() la fenêtre = Boucle
d'événement.la fenêtre

# vos assertions
soi.affirmerÉgal(la fenêtre.enfants[0], soi. bouton)
affirmerÉgal(
la fenêtre.enfants[0].la taille, la
fenêtre.la taille
)

Dans le deuxième cas de test, les deux mettre en place() et démolir() travailler avec GraphicUnitTest.render(). Voici la configuration de
base qu'il effectue automatiquement :

• La fenêtre est dimensionnée à 320 x 240 px

• Seule la configuration par défaut est utilisée pendant le test, elle est limitée par le
KIVY_USE_DEFAULTCONFIG variable d'environnement
• Toute entrée (souris/tactile/. . . ) est supprimé et si vous avez besoin de le tester, moquez-vous ou ajoutez-le manuellement

• Le canevas de la fenêtre est effacé avant d'afficher une arborescence de widgets

Avertissement: N'utilisez PAS de nombres absolus dans vos tests pour préserver la fonctionnalité dans toutes les résolutions. Au
lieu de cela, utilisez par exemple la position ou la taille relative et multipliez-la par leLa taille de la fenêtre dans ton essai.

à partir de kivy.tests.common importer Test d'unité graphique, UnitTestTouch

classer MonTestCase(Test d'unité graphique):

déf test_render(soi):
à partir de bouton kivy.uix importer Bouton

# avec GraphicUnitTest.render(), vous faites essentiellement ceci :


# runTouchApp(Button()) + quelques réglages avant
bouton = Bouton() soi.rendre(bouton)

# récupérez votre instance Window en toute sécurité à


partir de kivy.base importer Boucle d'événement
(suite à la page suivante)

14
(suite de la page précédente)

Boucle d'événement.assurer_fenêtre() la
fenêtre = Boucle d'événement.la fenêtre

toucher = UnitTestTouch(
* [s / 2.0 pour s dans la fenêtre.Taille]
)

# lier quelque chose pour tester le toucher avec


bouton.lier(
on_release=lambda exemple: régler(
exemple, 'test_publié', Vrai
)
)

# puis touchons le centre de la fenêtre toucher.


atterrissage() toucher.retouche()

soi.assertTrue(bouton.test_publié)

si __Nom__ == '__principale__':
importer Test de l'unité
Test de l'unité.principale()

Noter: Assurez-vous de vérifier la source de kivy.tests.common avant d'écrire des cas de test complets.

tests unitaires GL

Les tests unitaires GL sont plus difficiles. Vous devez savoir que même si OpenGL est un standard, la sortie/le rendu ne
l'est pas. Cela dépend de votre GPU et du pilote utilisé. Pour ces tests, le but est de sauvegarder la sortie du rendu à
l'image X, et de la comparer à une image de référence.

Actuellement, les images sont générées à 320x240 pixels, en png format.

Noter: Actuellement, la comparaison d'images se fait par pixel. Cela signifie que l'image de référence que vous générez ne sera
correcte que pour votre GPU/pilote. Si quelqu'un peut implémenter la comparaison d'images avec le support "delta", les
correctifs sont les bienvenus :)

Pour exécuter les tests unitaires GL, vous devez créer un répertoire :

mkdir kivy/essais/résultats
KIVY_UNITTEST_SCREENSHOTS=1 faire un test

Le répertoire des résultats contiendra toutes les images de référence et les images générées. Après la première
exécution, si le répertoire des résultats est vide, aucune comparaison ne sera effectuée. Il utilisera les images générées
comme référence. Après la deuxième exécution, toutes les images seront comparées aux images de référence.

Un fichier html est disponible pour montrer la comparaison avant/après le test, et un extrait du test
unitaire associé. Il sera généré à :

kivy/tests/build/index.html

15
Noter: Le répertoire de construction est nettoyé après chaque appel à faire un test. Si vous ne le souhaitez pas, utilisez simplement la commande
pytest.

Rédaction de tests unitaires GL

L'idée est de créer un widget racine, comme vous le feriez dans construire(), ou dans kivy.base.runTouchApp(). Vous
donnerez ce widget racine à une fonction de rendu qui capturera la sortie dans des images X.

Voici un exemple:

à partir de kivy.tests.common importer Test d'unité graphique

classer VertexInstructionTestCas(Test d'unité graphique):

déf test_ellipse(soi):
à partir de kivy.uix.widget importer Widget à partir
de kivy.graphics importer Ellipse, Couleur r = soi.
rendre

# créer un widget racine


largeur = Widget()

# mettre des instructions graphiques dessus


avec largeur.Toile:
Couleur(1, 1, 1)
soi.e = Ellipse(position=(100, 100), Taille=(200, 100))

# rendu et capture directement r(largeur)

# comme alternative, vous pouvez capturer en 2 images : r(


largeur, 2)

# ou en 10 images r(
largeur, dix)

Chaque appel à auto.rendu (ou r dans notre exemple) va générer une image nommée comme suit :

<nom du cours>_<nom de fonction>-<r-appeler-compter>.png

nombre d'appels représente le nombre de fois que auto.rendu est appelé à l'intérieur de la fonction de test.

Les images de référence sont nommées :

réf_<nom du cours>_<nom de fonction>-<r-appeler-compter>.png

Vous pouvez facilement remplacer l'image de référence par une nouvelle si vous le souhaitez.

16
Rapports de couverture

La couverture est basée sur l'exécution des tests précédents. Les statistiques sur la couverture du code sont automatiquement
calculées lors de l'exécution. Vous pouvez générer un rapport html de la couverture avec la commande :

Faire la couverture

Ensuite, ouvrez kivy/htmlcov/index.html avec votre navigateur Web préféré.

2.8 GSOC

2.8.1 Google Summer of Code - 2017

introduction

Kivy est une bibliothèque Python open source multiplateforme, conviviale et accélérée par GPU pour le développement
rapide d'applications utilisant des interfaces utilisateur innovantes, telles que des applications multi-touch.

L'organisation Kivy pilote plusieurs projets majeurs :


• Le Kivy Bibliothèque d'interface graphique

• Le Python-Pour-Android outil de compilation.

• Le Kivy-iOS outil de compilation.

• Le PyJNIus bibliothèque pour l'interfaçage avec Java de Python.

• Le PyOBJus bibliothèque pour l'interfaçage avec Objective-C de Python.

• Le Pince wrapper Python indépendant de la plate-forme pour les API dépendantes de la plate-forme.

• Buildozer - Un packager Python générique pour Android, iOS et ordinateur de bureau.

• KivEnt - Un moteur de jeu 2D qui fournit des méthodes optimisées pour gérer de grandes quantités de données visuelles
dynamiques.

• Concepteur Kivy - Un concepteur d'interface graphique pour Kivy intégré à Kivy.

Dans l'ensemble, ces projets permettent à l'utilisateur de créer des applications pour tous les principaux systèmes d'exploitation qui
utilisent toutes les API natives présentes. Notre objectif est de permettre le développement d'applications Python qui s'exécutent partout
sur la même base de code et qui utilisent des API et des fonctionnalités dépendantes de la plate-forme auxquelles les utilisateurs de
systèmes d'exploitation spécifiques s'attendent.

Selon le projet que vous choisissez, vous devrez peut-être connaître Cython, OpenGL ES2, Java, Objective-C ou C en plus
de Python. Nous utilisons massivement Cython et OpenGL pour les performances de calcul et graphiques là où cela
compte, et les autres langages sont généralement impliqués dans l'accès aux API au niveau du système d'exploitation
ou du fournisseur.

Nous espérons participer au Google Summer of Code 2017. Cette page présente quelques idées de projets
GSoC et les directives correspondantes pour les étudiants contribuant au framework Kivy.

17
Exigences

Il est supposé que l'étudiant entrant répond à certaines exigences de base, comme souligné ici :

• Connaissance de niveau intermédiaire avec Python.

• À l'aise avec git et github (Kivy et ses projets sœurs sont tous gérés sur github) Si vous n'avez jamais
utilisé github auparavant, cela peut vous intéresser Didacticiel.

• À l'aise avec la programmation événementielle.

• Dispose d'outils/d'un environnement adaptés à Kivy ou au projet jumeau sur lequel vous allez travailler. Par exemple, pour
pouvoir travailler sur PyOBJus, vous auriez besoin d'accéder à un appareil iOS, OS X avec Xcode et une licence de
développeur, pour travailler sur PyJNIus, vous auriez besoin d'un appareil Android, et pour travailler sur plier, vous auriez
besoin d'un accès au matériel pour les deux plates-formes.

Des compétences supplémentaires souhaitées peuvent être répertoriées avec des projets spécifiques.

Familiarisez-vous avec le guide de contribution Nous pouvons vous aider à vous mettre à niveau, mais les étudiants
démontrant leurs capacités à l'avance auront la préférence.

Comment commencer

Pour Kivy, le plus simple est de suivre les instructions d'installation de la version de développement pour votre
plateforme spécifique :

http://kivy.org/docs/installation/installation.html#development-version
Pour le reste, il suffit généralement d'installer le projet concerné depuis git et de l'ajouter à votre PYTHON-PATH.

par exemple pour PyJNIus :

git clone http://github.com/kivy/pyjnius export


PYTHONPATH=/path/to/pyjnius:$PYTHONPATH

Idées de projets

Voici quelques idées prospectives provenant de l'équipe de développement Kivy, si aucun de ces projets ne vous
intéresse, venez nous parler dans #kivy-dev d'une idée de projet qui vous est propre.

Projets pour débutants

Ces projets devraient convenir à toute personne connaissant Python au niveau universitaire et nécessitant peu de connaissances
sur les spécificités de la plate-forme.

Projets intermédiaires

Ces projets peuvent impliquer une connaissance superficielle de plusieurs détails au niveau du système d'exploitation, certaines
interactions OpenGL ou d'autres sujets qui peuvent être un peu hors de la timonerie du Pythonista moyen.

Joueur :

La description: Plyer est une API Python indépendante de la plate-forme pour utiliser les fonctionnalités couramment trouvées
sur les plates-formes de bureau et mobiles prises en charge par Kivy. L'idée est de fournir une API stable à l'utilisateur pour
accéder aux fonctionnalités de son ordinateur de bureau ou de son appareil mobile.

18
L'étudiant remplacerait certains .Java code actuellement dans le projet p4a à un endroit plus approprié dans
Plyer. En outre, l'étudiant travaillerait à l'amélioration de l'accès aux fonctionnalités spécifiques à la plate-
forme via Plyer, y compris l'accessibilité, Bluetooth Low Energy, l'accès et la modification des contacts, le
partage, NFC, navigateur intégré à l'application, Wi-Fi (activer, désactiver, accès à Wi- Services Fi (Wi-Fi direct,
accessibilité du réseau, informations IP actuelles sur le réseau, etc.), capture de l'appareil photo (vidéo),
affichage de l'appareil photo, intégration de Google Play, interface de lancement d'appel téléphonique,
interface sms, géolocalisation, interaction avec les notifications, internationalisation (I18N ) et toutes les
implémentations de plate-forme manquantes des fonctionnalités existantes.

Sous le capot, vous utiliserez PyJNIus sur Android, PyOBJus sur OS X et iOS, ctypes sur Windows et les
API natives sur Linux. Cela inclurait probablement également l'amélioration de PyOBJus et PyJNIus
pour gérer les interfaces qu'ils ne peuvent pas actuellement.

Les références:

• https://github.com/kivy/plyer
• https://github.com/kivy/pyjnius
• https://github.com/kivy/pyobjus
• https://github.com/kivy/python-for-android
• https://github.com/kivy/kivy-ios
Résultat attendu : Un résultat positif inclurait le déplacement du code Java/PyOBJus
de p4a/kivy-ios à plier et mise en place de tout ou partie des nouvelles façades à
décider avec l'étudiant.
• Mentors: Akshay Arora
• Exigences: Accès à Linux, Windows, OS X, appareil iOS, appareil Android.
• Niveau de tâche: Intermédiaire

• Compétences désirées: Familiarité avec PyJNIus, PyOBJus.

Prise en charge du remodelage des polices et de la restauration des polices

La description: Actuellement, Kivy ne prend pas en charge le remodelage des alphabets tels que l'arabe, le per-
sian, thaï ou devanagari. La solution est d'intégrer un moteur de mise en forme et de mise en page de texte
(Pango et Harfbuzz). Vous devrez vous assurer que Pango et Harfbuzz peuvent être compilés sur chaque
plate-forme et les intégrer en tant que fournisseur de texte de base.

La deuxième partie du même projet impliquerait la prise en charge des polices de secours. Si un caractère/glyphe particulier
est manquant, nous affichons actuellement une boîte []. La solution pour cela impliquerait soit d'utiliser une API de système
d'exploitation si disponible, soit de maintenir une table de hachage pour les polices par défaut sur chaque système
d'exploitation qui peut être utilisée pour le repli de glyphe.

Les références:

• http://www.pango.org
• https://www.freedesktop.org/wiki/Software/HarfBuzz/
• https://github.com/kivy/kivy/tree/master/kivy/core/text
Résultat attendu : Prise en charge du remplacement des polices et du remodelage du texte dans Kivy, recettes de compilation
pour Python-For-Android et packaging sur les plates-formes de bureau.

• Mentors: Akshay Arora, Jacob Kovac, Matthew Einhorn


• Exigences: Accès à un OS de bureau et idéalement à au moins une plateforme mobile

• Niveau de tâche: Intermédiaire

• Compétences désirées: Familiarité avec le rendu de texte, Pango, HarfBuzz et l'abstraction du fournisseur
de Kivy.

19
Projets avancés

Ces projets peuvent impliquer une connaissance très approfondie des éléments internes existants de Kivy, les détails délicats de
la compilation multiplateforme ou d'autres sujets assez avancés. Si vous êtes à l'aise avec les composants internes de Python,
que vous travaillez avec du code C et que vous utilisez Cython pour créer vos propres extensions C, ces projets peuvent vous
intéresser.

Kivent : Intégration Chipmunk 7

La description: KivEnt est un moteur de jeu modulaire basé sur des composants d'entités construit sur Kivy.
KivEnt fournit une approche hautement performante pour créer des jeux en Python qui évite certains des
pires frais généraux de Python en utilisant des constructions Cython spécialisées.

Pour le moment, KivEnt utilise en interne la bibliothèque cymunk (https://github. com/tito/cymunk)


pour la simulation physique et la détection de collision. Cymunk est basé sur Chipmunk2d 6.x,
récemment Chipmunk 7 a publié et introduit de nombreuses fonctionnalités auparavant premium
dans la bibliothèque principale. En plus des changements d'API présents dans le dernier Chipmunk,
le pont KivEnt - Cymunk n'utilise pas le plus efficacement possible l'API KivEnt pour gérer les objets et
les données de niveau C. L'étudiant sera responsable de la création d'un nouveau wrapper sur
Chipmunk2d 7 qui correspond mieux à l'approche de KivEnt en matière de gestion des données de
jeu.

Les références:

• http://chipmunk-physics.net/
• https://github.com/kivy/kivent
Résultat attendu : Un résultat positif implique qu'un nouveau module kivent_tiled soit re-
loué pour le moteur de jeu KivEnt.

• Mentors: Jacob Kovac


• Exigences: Accès à au moins une plateforme Kivy.
• Niveau de tâche: Avancée

• Compétences désirées: Familiarité avec les concepts mathématiques liés à Cython, Python et au développement de jeux.

Compilateur KV : un compilateur pour le langage KV

La description: Le langage KV est une composante fondamentale de Kivy. La langue KV


permet de décrire une interface graphique ; de la création d'une arborescence de widgets aux
actions à entreprendre en réponse aux changements de valeur et aux événements. En effet, il s'agit
d'un moyen concis de créer des liaisons de règles à l'aide des propriétés et des événements Kivy. En
interne, le code python qui reflète ces règles est créé et lié aux propriétés et aux événements.
Actuellement, ces liaisons ne sont pas du tout optimisées car à chaque création de widget, toutes ces
règles sont réévaluées et liées. Ce processus peut être considérablement optimisé en précompilant le
code kv, en particulier les liaisons. Un compilateur nous permettrait également de mettre à jour et de
résoudre certains des problèmes de langue kv de longue date.

Le travail sur un compilateur kv a déjà bien avancé, en fait un PR au stade pré-alpha est actuellement
ouvert. Cependant, il n'est pas synchronisé avec la base de code actuelle en raison de certains
changements de kv non liés entre-temps. En outre, ce PR nécessiterait une réécriture importante
pour rendre les choses plus modulaires, autonomes et extensibles. Il y a donc encore beaucoup de
travail à faire dessus.

La thématisation a également été un problème prépatuel dans Kivy, un compilateur KV peut aider à implémenter
des liaisons qui facilitent la thématisation.

Les références:

• https://kivy.org/docs/guide/lang.html

20
• https://github.com/kivy/kivy/pull/3456
• https://github.com/kivy/kivy/wiki/KEP001:-Instantiate-things-other-than-widgets-from-kv
• https://github.com/kivy/kivy/issues/691
• https://github.com/kivy/kivy/issues/2727
Résultat attendu : Un résultat positif serait un compilateur qui compile le code kv
en code python. Le compilateur doit être modulaire et extensible afin que nous puissions
continuer à améliorer le langage kv. Le compilateur doit avoir les options de débogage/
optimisation communes. Le code compilé doit également être lisible par l'homme afin que les
problèmes puissent être retracés jusqu'au code kv d'origine. Le compilateur devrait également
remplacer le compilateur d'exécution KV actuel et nécessiterait des tests approfondis.

• Mentors: Matthieu Einhorn


• Exigences: Accès à au moins une plateforme Kivy.
• Niveau de tâche: Avancée

• Compétences désirées: Familiarité avec Cython, Python et Kivy. Une connaissance des concepts
informatiques et des structures de données typiques est également souhaitée.

Comment contacter les développeurs

Toute communication doit se faire via des canaux publics, les e-mails privés et les messages privés Discord sont
découragés.

Posez vos questions sur le forum Kivy Users https://groups.google.com/group/kivy-users ou envoyer un


mail à kivy-users@googlegroups.com

Assurez-vous également de rejoindre le groupe d'utilisateurs kivy-dev : https://groups.google.com/forum/#!forum/kivy-dev.

Vous pouvez également essayer de nous contacter sur Discord, pour obtenir les poignées Discord des développeurs mentionnés ci-dessus, visitez
https://kivy.org/#aboutus.

Assurez-vous de lire le Règles de discorde avant de vous connecter. Se connecter à Discord.

La plupart de nos développeurs sont situés en Europe, en Inde et en Amérique du Nord, alors gardez à l'esprit les heures d'éveil typiques
de ces régions.

Comment être un bon élève

Si vous souhaitez participer en tant qu'étudiant et maximiser vos chances d'être accepté, commencez à nous parler dès
aujourd'hui et essayez de résoudre quelques petits problèmes pour vous habituer à notre flux de travail. Si nous savons que
vous pouvez bien travailler avec nous, vous aurez de bien meilleures chances d'être sélectionné.

Voici une liste de contrôle :

• Assurez-vous de lire le site Web et au moins de parcourir la documentation.

• Regardez le code source.

• Lisez nos directives de contribution.

• Contribuez ! Kivy aimerait voir comment vous vous engagez dans le processus de développement. Jetez un œil au traqueur
de problèmes pour un projet Kivy qui vous intéresse et soumettez une Pull Request. Il peut s'agir d'un simple bug ou d'un
changement de documentation. Nous cherchons à avoir une idée de votre façon de travailler, pas à évaluer vos capacités.
Ne vous inquiétez pas d'essayer de choisir quelque chose pour nous impressionner.

• Choisissez une idée que vous jugez intéressante dans la liste d'idées ou proposez votre propre idée.

21
• Fais quelques recherches toi-même. GSoC est une question de donner et recevoir, pas seulement une interaction unilatérale. Il
s'agit de vous essayer d'atteindre les objectifs convenus avec notre soutien. La force motrice principale dans tout cela devrait être,
évidemment, vous-même. De nombreux étudiants surgissent et demandent ce qu'ils doivent faire. Vous devez baser cette
décision sur vos intérêts et vos compétences. Montrez-nous que vous êtes sérieux et prenez l'initiative.

• Rédiger un brouillon proposition sur ce que tu veux faire. Incluez ce que vous comprenez de l'état
actuel du projet, ce que vous aimeriez améliorer, comment, etc.

• Discutez de cette proposition avec nous en temps opportun. Avoir un retour.

• Être patient! Surtout sur Discord. Nous essaierons de vous joindre si nous sommes disponibles. Sinon, envoyez un
e-mail et attendez. La plupart des questions sont déjà répondues dans les documents ou ailleurs et peuvent être
trouvées avec quelques recherches. Vos questions doivent refléter le fait que vous avez réellement réfléchi à ce
que vous demandez et effectué des recherches rudimentaires.

• Surtout n'oubliez pas de vous amuser et d'interagir avec la communauté. La communauté est une partie aussi importante
de l'Open Source que le code lui-même.

À quoi s'attendre si vous êtes choisi

• Tous les étudiants doivent rejoindre quotidiennement les canaux #support et #dev Discord, c'est ainsi que l'équipe de
développement communique à la fois en interne et avec les utilisateurs.

• Vous et vos mentors vous mettrez d'accord sur des jalons de deux semaines pour la durée de l'été.

• Le développement se fera dans votre fork de la branche master de Kivy, nous attendons de vous que vous soumettiez au
moins un PR par semaine depuis votre branche dans une branche qui vous est réservée dans le repo primaire. Ce sera
votre forum pour signaler les progrès ainsi que pour documenter toutes les difficultés que vous pourriez avoir
rencontrées.

• Manquer 2 RP hebdomadaires ou 2 jalons entraînera votre échec à moins qu'il n'y ait eu des circonstances
atténuantes. Si quelque chose survient, veuillez en informer vos mentors dès que possible. Si une étape
semble hors de portée, nous travaillerons avec vous pour réévaluer les objectifs.

• Vos modifications seront fusionnées dans le master une fois le projet terminé et nous avons
minutieusement testé sur chaque plate-forme pertinente.

22
CHAPITRE

TROIS

FAQ

Il y a un certain nombre de questions auxquelles il faut constamment répondre. Le document suivant tente de répondre à
certaines d'entre elles.

3.1 FAQ technique

3.1.1 Impossible d'obtenir une fenêtre, abandonnez.

Si Kivy ne peut pas instancier un fournisseur principal de Windows (principalement SDL2), vous le verrez. Le problème sous-jacent dépend
de beaucoup de choses :

• Vérifiez votre installation. À deux reprises.

• Vérifiez que votre pilote graphique prend en charge OpenGL 2.1 au minimum. Sinon, Kivy ne peut pas courir.

• Si vous utilisez Windows et ANGLE (KIVY_GL_BACKEND=angle_sdl2), vérifiez que vous avez le support
DirectX 9.

• Si votre plate-forme ne prend pas en charge OpenGL, SDL2 ne peut pas initialiser OpenGL.

• Ne mélangez pas l'architecture des dépendances (par exemple extensions Python 64 bits et 32 bits/SDL2)

• Ne mélangez pas l'installation de Python : par exemple, si vous avez installé Python et Anaconda, le Python réellement
exécuté peut être différent de ce que vous pensez. De même, si vous avez plusieurs versions de Python disponibles sur le
CHEMIN, ils peuvent s'affronter.

• Vérifiez votre PATH pour vous assurer que les autres programmes qu'il contient ne fournissent pas les mêmes DLL que Kivy/Python, sinon des
problèmes peuvent se produire.

– Cela se produit généralement si un autre programme qui utilise des dépendances similaires à Kivy s'ajoute au
CHEMIN de sorte que les dépendances de Kivy se heurtent aux leurs.

– Lisez s'il vous plaît cette et cette pour plus de détails sur CHEMIN.

– Le meilleur outil pour résoudre ce problème est avec Dépendance Walker expliqué ici et ici.
– Mais assurez-vous de le lancer à partir de l'environnement identique dans lequel vous démarrez Python.

• Assurez-vous que toutes les dépendances sont installées (comme kivy_deps.sdl2).

• Peut-être que vos pilotes ont des symboles OpenGL manquants ? Essayez de passer à un autre backend
graphique avecKIVY_GL_BACKEND.

• Peut-être que votre La configuration de Pycharm est incorrecte.

23
3.1.2 Erreur fatale de Python : (pygame parachute) Défaut de segmentation

La plupart du temps, ce problème est dû à l'utilisation d'anciens pilotes graphiques. Installez le dernier pilote graphique
disponible pour votre carte graphique, et cela devrait être ok.

Sinon, cela signifie que vous avez probablement déclenché du code OpenGL sans contexte OpenGL disponible. Si vous
chargez des images, des atlas, en utilisant des instructions graphiques, vous devez d'abord générer une fenêtre :

# méthode 1 (préférée) à partir de


kivy.base importer EventLoop EventLoop.
assurer_fenêtre()

# méthode 2
à partir de kivy.core.window importer Fenêtre

Sinon, veuillez signaler un problème détaillé sur github en suivant les instructions dans le Signaler un problème partie
de la Contribuant Documentation. C'est très important pour nous car ce genre d'erreur peut être très difficile à
déboguer. Donnez-nous toutes les informations que vous pouvez donner sur votre environnement et votre exécution.

3.1.3 symbole non défini : glGenerateMipmap

Votre carte graphique ou ses pilotes sont peut-être trop vieux. Mettez à jour vos pilotes graphiques vers la dernière version disponible et
réessayez.

3.1.4 ImportError : aucun module nommé événement

Si vous utilisez Kivy depuis notre version de développement, vous devez le compiler avant de l'utiliser. Dans le répertoire kivy, faites :

faire force

3.2 FAQ Android

3.2.1 impossible d'extraire les données publiques

Ce message d'erreur peut se produire dans diverses circonstances. Veiller à ce que:

• vous avez un téléphone avec une carte SD

• vous n'êtes pas actuellement en mode « stockage de masse USB »

• vous avez les autorisations pour écrire sur la carte SD

Dans le cas de l'erreur du mode « Stockage de masse USB », et si vous ne souhaitez pas continuer à débrancher l'appareil, définissez
l'option USB sur Alimentation.

24
3.2.2 Crash lors de l'interaction tactile sur Android 2.3.x

Il y a eu des rapports de plantages sur les appareils basés sur Adreno 200/205. Sinon, les applications fonctionnent correctement mais se
bloquent lorsqu'elles interagissent avec / via l'écran.

Ces rapports mentionnaient également le problème en cours de résolution lors du passage à une ROM ICS ou supérieure.

3.2.3 Est-il possible d'avoir une application kiosque sur Android 3.0 ?

Thomas Hansen a écrit une réponse détaillée sur la liste de diffusion kivy-users :

https://groups.google.com/d/msg/kivy-users/QKoCekAR1c0/yV-85Y_iAwoJ
Fondamentalement, vous devez rooter l'appareil, supprimer le package SystemUI, ajouter quelques lignes à la configuration
XML, et vous avez terminé.

3.2.4 Quelle est la différence entre python-for-android de Kivy et SL4A ?

Bien qu'il porte le même nom, le python-for-android de Kivy n'est pas lié au projet python-for-android de SL4A, Py4A ou
android-python27. Ce sont des projets distinctement différents avec des objectifs différents. Vous pourrez peut-être
utiliser Py4A avec Kivy, mais aucun code ou effort n'a été fait pour le faire. L'équipe Kivy estime que notre python-for-
android est la meilleure solution pour nous à l'avenir, et les tentatives d'intégration et de prise en charge de Py4A ne
sont pas une bonne utilisation de notre temps.

3.3 FAQ sur le projet

3.3.1 Pourquoi utilisez-vous Python ? N'est-ce pas lent?

Essayons de donner une réponse complète ; s'il vous plaît soyez indulgent avec nous.

Python est un langage très agile qui vous permet de faire beaucoup de choses en peu de temps (par comparaison). Pour de
nombreux scénarios de développement, nous préférons fortement écrire notre application rapidement dans un langage de haut
niveau tel que Python, la tester, puis éventuellement l'optimiser.

Mais qu'en est-il de la vitesse ? Si vous comparez les vitesses d'exécution des implémentations pour un certain ensemble
d'algorithmes (en particulier le calcul des nombres), vous constaterez que Python est beaucoup plus lent que, disons, C++.
Maintenant, vous êtes peut-être encore plus convaincu que ce n'est pas une bonne idée dans notre cas d'utiliser Python.
Dessiner des graphiques sophistiqués (et nous ne parlons pas ici de l'OpenGL de votre grand-mère) est assez coûteux en calcul
et étant donné que nous voulons souvent le faire pour des expériences utilisateur riches, ce serait un argument juste. Mais,
dans pratiquement tous les cas, votre application finit par passer la plupart du temps (de loin) à exécuter la même partie du
code. Dans Kivy, par exemple, ces parties sont la répartition des événements et le dessin graphique. Maintenant, Python vous
permet de faire quelque chose pour rendre ces parties beaucoup plus rapides.

En utilisant Cython, vous pouvez compiler votre code jusqu'au niveau C, et à partir de là, votre compilateur C habituel
optimise les choses. C'est un processus assez simple et si vous ajoutez quelques astuces à votre code, le résultat devient
encore plus rapide. Nous parlons d'une accélération des performances d'un facteur compris entre 1x et jusqu'à plus de
1000x (cela dépend beaucoup de votre code). Chez Kivy, nous l'avons fait pour vous et avons implémenté les portions de
notre code, où l'efficacité est vraiment critique, au niveau C.

Pour le dessin graphique, nous utilisons également les GPU d'aujourd'hui qui sont, pour certaines tâches telles que la
rastérisation graphique, beaucoup plus efficace qu'un CPU. Kivy fait tout ce qui est raisonnable sur le GPU pour maximiser les
performances. Si vous utilisez notre API Canvas pour faire le dessin, il existe même un compilateur que nous avons inventé qui
optimise automatiquement votre code de dessin. Si vous conservez votre dessin principalement sur le GPU, une grande partie
de la vitesse d'exécution de votre programme n'est pas déterminée par le langage de programmation utilisé, mais par le
matériel graphique que vous lui lancez.

25
Nous pensons que ces optimisations (et d'autres) que Kivy fait pour vous rendent déjà la plupart des applications assez
rapides de loin. Souvent, vous voudrez même limiter la vitesse de l'application afin de ne pas gaspiller de ressources.
Mais même si cela ne suffit pas, vous avez toujours la possibilité d'utiliser Cython pour votre propre code afin detrès
accélérer.

Faites-nous confiance lorsque nous disons que nous avons réfléchi très attentivement. Nous avons effectué de nombreux tests
de performances et proposé des optimisations intelligentes pour que votre application fonctionne sans problème.

3.3.2 Kivy prend-il en charge Python 3.x ?

Oui! Depuis la version 1.8.0, Kivy prend en charge à la fois Python >= 2.7 et Python >= 3.4 avec la même base de code. Python 3
est également désormais pris en charge par python-for-android et kivy-ios.

3.3.3 Comment Kivy est-il lié à PyMT ?

Nos développeurs sont des professionnels et sont assez avertis dans leur domaine d'expertise. Cependant, avant
l'arrivée de Kivy, il y avait (et est toujours) un projet nommé PyMT qui était dirigé par nos principaux développeurs. Nous
avons beaucoup appris de ce projet pendant que nous l'avons développé. En plus de deux ans de recherche et
développement, nous avons trouvé de nombreuses façons intéressantes d'améliorer la conception de notre cadre. Nous
avons effectué de nombreux tests de performances et, en fin de compte, pour atteindre la grande vitesse et la flexibilité
dont dispose Kivy, nous avons dû réécrire une assez grande partie de la base de code, ce qui en fait une décision
rétrocompatible mais pérenne. Les plus notables sont les augmentations de performances, qui sont tout simplement
incroyables. Kivy démarre et fonctionne tellement plus rapidement, en raison de ces optimisations lourdes. Nous avons
également eu l'opportunité de travailler avec des entreprises et des associations utilisant PyMT. Nous avons pu tester
notre produit sur une grande diversité de configurations et avons fait fonctionner PyMT sur toutes. Écrire un système
comme Kivy ou PyMT est une chose. Le faire fonctionner dans toutes ces conditions différentes en est une autre. Nous
avons une bonne expérience ici et avons apporté nos connaissances à Kivy.

De plus, étant donné que certains de nos développeurs principaux ont décidé d'abandonner leurs emplois à temps plein et de se
tourner complètement vers ce projet, il a été décidé qu'une base plus professionnelle devait être posée. Kivy est cette fondation.
C'est censé être un produit stable et professionnel. Techniquement, Kivy n'est pas vraiment un successeur de PyMT car il n'y a
pas de chemin de migration facile entre eux. Cependant, l'objectif est le même : produire des applications de haute qualité pour
de nouvelles interfaces utilisateur. C'est pourquoi nous encourageons tout le monde à baser de nouveaux projets sur Kivy au
lieu de PyMT. Le développement actif de PyMT est au point mort. Les correctifs de maintenance sont toujours acceptés.

3.3.4 Acceptez-vous les correctifs ?

Oui, nous aimons les patchs. Cependant, afin d'assurer une intégration harmonieuse de vos précieuses modifications, assurez-
vous de lire nos directives de contribution. Évidemment, nous n'acceptons pas tous les patchs. Votre patch doit être cohérent
avec notre guide de style et, plus important encore, avoir du sens. Il est logique de nous parler avant de proposer des
changements plus importants, en particulier de nouvelles fonctionnalités.

3.3.5 Le projet Kivy participe-t-il au Summer of Code de Google ?

Les étudiants potentiels demandent si nous participons au GSoC. La réponse claire est : En effet. :-)

Si vous souhaitez participer en tant qu'étudiant et maximiser vos chances d'être accepté, commencez à nous parler dès
aujourd'hui et essayez de résoudre des problèmes plus petits (ou plus gros, si vous le pouvez ;-) pour vous habituer à notre flux
de travail. Si nous savons que vous pouvez bien travailler avec nous, ce serait un gros plus.

Voici une liste de contrôle :

• Assurez-vous de lire le site Web et au moins de parcourir la documentation.

• Regardez le code source.

26
• Lisez nos directives de contribution.

• Choisissez une idée qui vous semble intéressante dans la liste d'idées (voir le lien ci-dessus) ou proposez votre
propre idée.

• Fais quelques recherches toi-même. GSoC ne consiste pas à vous enseigner quelque chose et à vous faire payer pour cela.
Il s'agit de vous essayer d'atteindre les objectifs convenus par vous-même avec notre soutien. La force motrice principale
dans tout cela devrait être, évidemment, vous-même. De nombreux étudiants viennent et demandent ce qu'ils doivent
faire. Eh bien, nous ne savons pas parce que nous ne connaissons ni vos intérêts ni vos compétences. Montrez-nous que
vous êtes sérieux et prenez des initiatives.

• Rédigez une ébauche de proposition sur ce que vous voulez faire. Incluez ce que vous comprenez dans l'état actuel
(très grossièrement), ce que vous aimeriez améliorer et comment, etc.

• Discutez de cette proposition avec nous en temps opportun. Avoir un retour.

• Être patient! Surtout sur Discord. Nous essaierons de vous joindre si nous sommes disponibles. Sinon, envoyez un
e-mail et attendez. La plupart des questions sont déjà répondues dans les documents ou ailleurs et peuvent être
trouvées avec quelques recherches. Si vos questions ne reflètent pas que vous avez réellement réfléchi à ce que
vous demandez, cela pourrait ne pas être bien reçu.

Bonne chance! :-)

27
28
CHAPITRE

QUATRE

NOUS CONTACTER

Vous pouvez nous contacter de plusieurs manières différentes :

4.1 Suivi des problèmes

Si vous avez trouvé un problème avec le code ou avez une demande de fonctionnalité, veuillez consulter notre Traqueur d'incidents. S'il
n'y a pas encore de problème qui correspond à votre demande, n'hésitez pas à en créer un nouveau. Veuillez vous assurer de recevoir les
e-mails que github envoie si nous commentons le problème au cas où nous aurions besoin de plus d'informations. Pour les bogues,
veuillez fournir toutes les informations nécessaires, comme le système d'exploitation que vous utilisez, lemessage d'erreur complet ou
tout autre journal, une description de ce que vous avez fait pour déclencher le bogue et quel était le bogue réel, ainsi que tout autre
élément susceptible de vous intéresser. Évidemment, nous ne pouvons vous aider que si vous nous dites précisément quel est le
problème réel.

4.2 Courrier

Pour les utilisateurs de notre framework, il existe une liste de diffusion pour les demandes d'assistance sur le kivy-users Google Group.
Utilisez cette liste si vous rencontrez des problèmes avec votre application basée sur Kivy. Nous avons également une liste de diffusion
pour les questions qui traitent du développement du code du cadre Kivy réel sur leGroupe Google kivy-dev.

4.3 Discorde

Kivy sur Discord sur https://chat.kivy.org

Discord est idéal pour la communication en temps réel, mais assurez-vous de attendre après avoir posé votre question. Si vous vous
inscrivez, demandez et quittez, nous avonscertainement pas de savoir qui vous étiez et où nous sommes censés envoyer notre réponse.
De plus, gardez à l'esprit que nous sommes principalement basés en Europe, alors tenez compte des problèmes de fuseau horaire. Si
vous êtes malchanceux plus d'une fois, essayez la liste de diffusion.

Si vous n'avez pas l'application Discord, vous pouvez également utiliser Le client Web de Discord, mais s'il vous plaît, ne partez pas trop
tôt. Assurez-vous simplement de demander sur le #Support canaliser.

Veuillez lire notre Règles de la communauté avant de demander de l'aide sur la liste de diffusion ou le canal Discord.

29
30
deuxieme PARTIE

GUIDE DE PROGRAMMATION

31
32
CHAPITRE

CINQ

BASES DE KIVY

5.1 Installation de l'environnement Kivy

Kivy dépend de nombreuses bibliothèques Python, telles que pygame, gstreamer, PIL, Cairo, etc. Ils ne sont pas tous
nécessaires, mais selon la plate-forme sur laquelle vous travaillez, ils peuvent être difficiles à installer. Pour Windows et MacOS
X, nous fournissons un package portable que vous pouvez simplement décompresser et utiliser.

Consultez l'une de ces pages pour obtenir des instructions d'installation détaillées :

• installation_windows
• installation_osx
• installation_linux
• installation_rpi
Vous pouvez également trouver des instructions pour la version de développement ici :

• montage

5.2 Créer une candidature

Créer une application Kivy est aussi simple que :

• sous-classer le Application classer

• mettre en œuvre son construire() méthode afin qu'elle renvoie un Widget instance (la racine de votre arbre de widgets)

• en instanciant cette classe, et en appelant sa Cours() méthode.

Voici un exemple d'application minimale :

importer kivy
kivy.exiger('1.0.6') # remplacer par votre version actuelle de Kivy !

à partir de kivy.app importer Application à partir


de kivy.uix.label importer Étiqueter

classer MonApp(Application):

déf construire(soi):
retourner Étiqueter(texte='Bonjour le monde')

(suite à la page suivante)

33
(suite de la page précédente)

si __Nom__ == '__principale__':
MonApp().Cours()

Vous pouvez l'enregistrer dans un fichier texte, main.py par exemple, et exécutez-le.

5.3 Cycle de vie de l'application Kivy

Tout d'abord, familiarisons-nous avec le cycle de vie de l'application Kivy.

Comme vous pouvez le voir ci-dessus, à toutes fins utiles, notre point d'entrée dans notre application est la méthode
run(), et dans notre cas, c'est "MyApp().run()". Nous y reviendrons, mais commençons par la ligne :

à partir de kivy.app importer Application

Il est nécessaire que la classe de base de votre application hérite de la Application classer. Il est présent dans le
répertoire kivy_installation_dir/kivy/app.py.

Noter: Allez-y et ouvrez ce fichier si vous souhaitez approfondir ce que fait la classe Kivy App. Nous vous
encourageons à ouvrir le code et à le lire. Kivy est basé sur Python et utilise Sphinx pour la documentation, donc
la documentation de chaque classe se trouve dans le fichier réel.

De même à la ligne 5 :

34
à partir de kivy.uix.label importer Étiqueter

Une chose importante à noter ici est la façon dont les packages/classes sont organisés. leuix module est la section qui contient
les éléments de l'interface utilisateur tels que les mises en page et les widgets.

Passons à la ligne 8 :

classer MonApp(Application):

C'est là que nous sommes définir la classe de base de notre application Kivy. Vous ne devriez jamais avoir besoin de changer le nom de
votre applicationMonApp dans cette ligne.

Plus loin à la ligne 10 :

déf construire(soi):

Comme le montre l'image ci-dessus, montrez le boîtier du Cycle de vie de l'application Kivy, c'est la fonction où vous
devez initialiser et retourner votre Widget racine. Voici ce que nous faisons à la ligne 11 :

retourner Étiqueter(texte='Bonjour le monde')

Ici, nous initialisons une étiquette avec le texte « Hello World » et renvoyons son instance. Cette étiquette sera le widget racine
de cette application.

Noter: Python utilise l'indentation pour désigner les blocs de code, notez donc que dans le code fourni ci-dessus, à la
ligne 11, la définition de la classe et de la fonction se termine.

Passons maintenant à la partie qui fera fonctionner notre application aux lignes 14 et 15 :

si __Nom__ == '__principale__':
MonApp().Cours()

Ici la classe MonApp est initialisé et sa méthode run() est appelée. Cela initialise et démarre notre
application Kivy.

5.4 Exécution de l'application

Pour exécuter l'application, suivez les instructions correspondant à votre système d'exploitation :

Pour Windows, Linux, OS X ou le RPi. DuTerminal où vous avez installé Kivy, exécutez simplement :

Python principal.py

Pour Android ou iOS, votre application a besoin de fichiers complémentaires pour pouvoir s'exécuter. VoirCréer un
package pour Android ou voir Créer un package pour IOS pour plus de référence.

Une fenêtre devrait s'ouvrir, affichant une seule étiquette (avec le texte « Hello World ») qui couvre toute la zone de la
fenêtre. C'est tout ce qu'on peut en dire.

35
Traduit de Anglais vers Français - www.onlinedoctranslator.com

à partir de kivy.uix.label importer Étiqueter

Une chose importante à noter ici est la façon dont les packages/classes sont organisés. leuix module est la section qui contient
les éléments de l'interface utilisateur tels que les mises en page et les widgets.

Passons à la ligne 8 :

classer MonApp(Application):

C'est là que nous sommes définir la classe de base de notre application Kivy. Vous ne devriez jamais avoir besoin de changer le nom de
votre applicationMonApp dans cette ligne.

Plus loin à la ligne 10 :

déf construire(soi):

Comme le montre l'image ci-dessus, montrez le boîtier du Cycle de vie de l'application Kivy, c'est la fonction où vous
devez initialiser et retourner votre Widget racine. Voici ce que nous faisons à la ligne 11 :

retourner Étiqueter(texte='Bonjour le monde')

Ici, nous initialisons une étiquette avec le texte « Hello World » et renvoyons son instance. Cette étiquette sera le widget racine
de cette application.

Noter: Python utilise l'indentation pour désigner les blocs de code, notez donc que dans le code fourni ci-dessus, à la
ligne 11, la définition de la classe et de la fonction se termine.

Passons maintenant à la partie qui fera fonctionner notre application aux lignes 14 et 15 :

si __Nom__ == '__principale__':
MonApp().Cours()

Ici la classe MonApp est initialisé et sa méthode run() est appelée. Cela initialise et démarre notre
application Kivy.

5.4 Exécution de l'application

Pour exécuter l'application, suivez les instructions correspondant à votre système d'exploitation :

Pour Windows, Linux, OS X ou le RPi. DuTerminal où vous avez installé Kivy, exécutez simplement :

Python principal.py

Pour Android ou iOS, votre application a besoin de fichiers complémentaires pour pouvoir s'exécuter. VoirCréer un
package pour Android ou voir Créer un package pour IOS pour plus de référence.

Une fenêtre devrait s'ouvrir, affichant une seule étiquette (avec le texte « Hello World ») qui couvre toute la zone de la
fenêtre. C'est tout ce qu'on peut en dire.

35
5.5 Personnaliser l'application

Étendons un peu cette application, disons une simple page de nom d'utilisateur/mot de passe.

à partir de kivy.app importer Application


à partir de kivy.uix.gridlayout importer Disposition de la grille
à partir de kivy.uix.label importer Étiqueter à partir de
kivy.uix.textinput importer Saisie de texte

classer Écran de connexion(Disposition de la grille):

déf __init__(soi, **kwargs):


super(Écran de connexion, soi).__init__(**kwargs) soi.cols
=2
soi.add_widget(Étiqueter(texte='Nom d'utilisateur')) soi.
Nom d'utilisateur = Saisie de texte(multiligne=Faux) soi.
add_widget(soi.Nom d'utilisateur)
soi.add_widget(Étiqueter(texte='le mot de passe'))
soi.le mot de passe = Saisie de texte(le mot de passe=Vrai, multiligne=Faux)
soi.add_widget(soi.le mot de passe)

classer MonApp(Application):

déf construire(soi):
retourner Écran de connexion()

si __Nom__ == '__principale__':
MonApp().Cours()

A la ligne 2, nous importons un Disposition de la grille:

36
à partir de kivy.uix.gridlayout importer Disposition de la grille

Cette classe est utilisée comme Base pour notre Root Widget (LoginScreen) défini à la ligne 7 :

classer Écran de connexion(Disposition de la grille):

A la ligne 9 de la classe LoginScreen, on surcharge la méthode __init__() afin d'ajouter des widgets et de définir
leur comportement :

déf __init__(soi, **kwargs):


super(Écran de connexion, soi).__init__(**kwargs)

Il ne faut pas oublier d'appeler super pour implémenter la fonctionnalité de la classe d'origine surchargée. Notez
également qu'il est de bonne pratique de ne pas omettre le**kwargs tout en appelant super, car ils sont parfois
utilisés en interne.

Passons à la ligne 11 et au-delà :

soi.cols = 2
soi.add_widget(Étiqueter(texte='Nom d'utilisateur')) soi.
Nom d'utilisateur = Saisie de texte(multiligne=Faux) soi.
add_widget(soi.Nom d'utilisateur)
soi.add_widget(Étiqueter(texte='le mot de passe'))
soi.le mot de passe = Saisie de texte(le mot de passe=Vrai, multiligne=Faux)
soi.add_widget(soi.le mot de passe)

Nous demandons au GridLayout de gérer ses enfants en deux colonnes et d'ajouter un Étiqueter et un Saisie de texte pour le nom
d'utilisateur et le mot de passe.

L'exécution du code ci-dessus vous donnera une fenêtre qui devrait ressembler à ceci :

Essayez de redimensionner la fenêtre et vous verrez que les widgets à l'écran s'ajustent en fonction de la taille de la
fenêtre sans que vous ayez à faire quoi que ce soit. C'est parce que les widgets utilisent l'indication de taille par défaut.

Le code ci-dessus ne gère pas les entrées de l'utilisateur, ne fait aucune validation ou quoi que ce soit d'autre. Nous
allons approfondir cela etWidget taille et positionnement dans les sections à venir.

37
38
CHAPITRE

SIX

MAÎTRISER L'ENVIRONNEMENT

De nombreuses variables d'environnement sont disponibles pour contrôler l'initialisation et le comportement de Kivy.

Par exemple, afin de restreindre le rendu du texte à l'implémentation PIL :

$ KIVY_TEXT=pil python main.py

Les variables d'environnement doivent être définies avant d'importer kivy :

importer système d'exploitation

système d'exploitation.environ[ = 'pil'


'KIVY_TEXT'] importer kivy

6.1 Contrôle de chemin

Nouveau dans la version 1.0.7.

Vous pouvez contrôler les répertoires par défaut où se trouvent les fichiers de configuration, les modules et les données kivy.

KIVY_DATA_DIR Emplacement des données Kivy, par défaut <chemin kivy>/données

KIVY_MODULES_DIR Emplacement des modules Kivy, par défaut <chemin kivy>/modules

KIVY_HOME Localisation de la maison Kivy. Ce répertoire est utilisé pour la configuration locale et doit être
dans un endroit inscriptible.

Par défaut :

• Bureau : <accueil utilisateur>/.kivy

• Android: <chemin de l'application Android>/.kivy

• iOS : <accueil utilisateur>/Documents/.kivy

Nouveau dans la version 1.9.0.

KIVY_SDL2_PATH Si défini, les bibliothèques SDL2 et les en-têtes de ce chemin sont utilisés lors de la compilation de kivy
au lieu de ceux installés à l'échelle du système. Pour utiliser les mêmes bibliothèques lors de l'exécution d'une application
kivy, ce chemin doit être ajouté au début de la variable d'environnement PATH.

Nouveau dans la version 1.9.0.

Avertissement: Ce chemin est requis pour la compilation de Kivy. Il n'est pas nécessaire pour l'exécution du
programme.

39
6.2 Paramétrage

KIVY_USE_DEFAULTCONFIG Si ce nom est trouvé dans environ, Kivy ne lira pas la configuration utilisateur
déposer.

KIVY_NO_CONFIG S'il est défini, aucun fichier de configuration ne sera lu ou écrit. Ceci s'applique également à l'utilisateur
répertoire de configuration.

KIVY_NO_FILELOG Si défini, les journaux ne seront pas imprimés dans un fichier

KIVY_NO_CONSOLELOG Si défini, les journaux ne seront pas imprimés sur la console

KIVY_NO_ARGS S'il est défini sur l'un des ('true', '1', 'yes'), l'argument passé en ligne de commande ne sera pas
analysé et utilisé par Kivy. C'est-à-dire que vous pouvez créer en toute sécurité un script ou une application avec vos propres
arguments sans avoir besoin du– délimiteur :

importer système d'exploitation

système d'exploitation.environ[ = "1"


"KIVY_NO_ARGS"] importer kivy

Nouveau dans la version 1.9.0.

KCFG_section_key Si un tel nom d'environnement de format est détecté, il sera mappé à la configuration
objet. Ils ne sont chargés qu'une seule fois lorsquekivy est importé. Le comportement peut être désactivé en
utilisant KIVY_NO_ENV_CONFIG.

importer système d'exploitation

système d'exploitation.environ["KCFG_KIVY_LOG_LEVEL" = "avertissement"


] importer kivy
# lors de l'importation, il le mappera sur :
# Config.set("kivy", "log_level", "avertissement")

Nouveau dans la version 1.11.0.

KIVY_NO_ENV_CONFIG Si elle est définie, aucune clé d'environnement ne sera mappée à l'objet de configuration. S'il n'est pas réglé,
quelconque KCFG_section_key=valeur sera mappé sur Config.

Nouveau dans la version 1.11.0.

6.3 Restreindre le noyau à une mise en œuvre spécifique

kivy.core essayez de sélectionner la meilleure implémentation disponible pour votre plate-forme. Pour les tests ou l'installation
personnalisée, vous souhaiterez peut-être restreindre le sélecteur à une implémentation spécifique.

KIVY_WINDOW Implémentation à utiliser pour créer la fenêtre


Valeurs : sdl2, pygame, x11, egl_rpi

KIVY_TEXT Implémentation à utiliser pour le rendu du texte

Valeurs : sdl2, pil, pygame, sdlttf

KIVY_VIDEO Implémentation à utiliser pour le rendu vidéo

Valeurs : gstplayer, ffpyplayer, ffmpeg, null

KIVY_AUDIO Implémentation à utiliser pour la lecture audio

Valeurs : sdl2, gstplayer, ffpyplayer, pygame, avplayer

KIVY_IMAGE Implémentation à utiliser pour la lecture d'image

Valeurs : sdl2, pil, pygame, imageio, tex, dds, gif

40
KIVY_CAMERA Implémentation à utiliser pour la caméra de lecture

Valeurs : avfoundation, android, opencv

KIVY_SPELLING Implémentation à utiliser pour l'orthographe

Valeurs : enchanter, osxappkit

KIVY_CLIPBOARD Implémentation à utiliser pour la gestion du presse-papiers

Valeurs : sdl2, pygame, dummy, android

6.4 Métriques

KIVY_DPI Si elle est définie, la valeur sera utilisée pour Métriques.dpi.

Nouveau dans la version 1.4.0.

KIVY_METRICS_DENSITY Si elle est définie, la valeur sera utilisée pour Métriques.densité.

Nouveau dans la version 1.5.0.

KIVY_METRICS_FONTSCALE
Si elle est définie, la valeur sera utilisée pour Métriques.fontscale.

Nouveau dans la version 1.5.0.

6.5 Graphiques

KIVY_GL_BACKEND Le backend OpenGL à utiliser. Voircgl.


KIVY_GL_DEBUG S'il faut enregistrer les appels OpenGL. Voircgl.

KIVY_GRAPHICS S'il faut utiliser OpenGL ES2. Voircgl.


KIVY_GLES_LIMITS Si les restrictions GLES2 sont appliquées (valeur par défaut, ou si définie sur 1). Si réglé sur
false, Kivy ne sera pas vraiment compatible GLES2.

Voici une liste des incompatibilités potentielles qui se produisent lorsqu'elles sont définies sur true.

Engrener Si vrai, le nombre d'indices dans un maillage est limité à 65535


dans-

dés
Texas- Lors du blitting à une texture, le format des données (couleur et tampon) doit être le même que celui utilisé
ture lors de la création de la texture. Sur le bureau, la conversion des différentes couleurs est correctement gérée
blit par le pilote, tandis que sur Android, la plupart des appareils ne le font pas. Réf :https://github. com/kivy/
kivy/issues/1600

Nouveau dans la version 1.8.1.

KIVY_BCM_DISPMANX_ID Modifiez l'affichage par défaut du Raspberry Pi à utiliser. La liste des disponibles
la valeur est accessible dans vc_dispmanx_types.h. La valeur par défaut est 0 :

• 0 : DISPMANX_ID_MAIN_LCD
• 1 : DISPMANX_ID_AUX_LCD
• 2 : DISPMANX_ID_HDMI
• 3 : DISPMANX_ID_SDTV
• 4: DISPMANX_ID_FORCE_LCD

41
• 5 : DISPMANX_ID_FORCE_TV
• 6 : DISPMANX_ID_FORCE_OTHER
KIVY_BCM_DISPMANX_LAYER Modifiez la couche dispmanx par défaut de Raspberry Pi. La valeur par défaut est
0.
Nouveau dans la version 1.10.1.

6.6 Boucle d'événement

KIVY_EVENTLOOP Quelle bibliothèque asynchrone doit être utilisée lorsque l'application est exécutée de manière asynchrone
manière. Voirkivy.app par exemple l'utilisation.

'asyncio' : Lorsque l'application est exécutée de manière asynchrone et que la norme bibliothèque asy-
cio package doit être utilisé. La valeur par défaut si elle n'est pas définie.

'trio': Lorsque l'application est exécutée de manière asynchrone et que le trio paquet devrait être
utilisé.

Nouveau dans la version 2.0.0.

42
CHAPITRE

SEPT

CONFIGURER KIVY

Le fichier de configuration pour kivy est nommé config.ini, et adhère aux INI standard format.

7.1 Localisation du fichier de configuration

L'emplacement du fichier de configuration est contrôlé par la variable d'environnement KIVY_HOME:

<KIVY_HOME>/configuration.ini

Sur le bureau, cela est par défaut :

<HOME_DIRECTORY>/.kivy/configuration.ini

Par conséquent, si votre utilisateur se nomme « tito », le fichier sera ici :

• Les fenêtres: C:\Users\tito\.kivy\config.ini


• OS X : /Users/tito/.kivy/config.ini
• Linux : /home/tito/.kivy/config.ini
Sur Android, cette valeur par défaut est :

<ANDROID_APP_PATH>/.kivy/configuration.ini

Si votre application s'appelle « org.kivy.launcher », le fichier sera ici :

/Les données/Les données/organisation.kivy.lanceur/des dossiers/.kivy/configuration.ini

Sur iOS, cette valeur par défaut est :

<HOME_DIRECTORY>/Documents/.kivy/configuration.ini

7.2 Configuration locale

Parfois, il est souhaitable de modifier la configuration uniquement pour certaines applications ou lors du test d'une partie
distincte de Kivy, par exemple les fournisseurs d'entrée. Pour créer un fichier de configuration séparé, vous pouvez simplement
utiliser ces commandes :

à partir de kivy.config importer Configuration

Configuration.lire(<déposer>)
(suite à la page suivante)

43
(suite de la page précédente)

# définir la configuration

Configuration.écrivez()

Lorsqu'une configuration locale de single .ini file n'est pas suffisant, par exemple lorsque vous voulez avoir un environnement
séparé pour jardin, les journaux kivy et d'autres choses, vous devrez changer le KIVY_HOME variable d'environnement dans
votre application pour obtenir le résultat souhaité :

importer système d'exploitation

système d'exploitation.environ['KIVY_HOME'] = <dossier>

ou avant chaque exécution de l'application modifiez-la manuellement dans la console :

1. Fenêtres :

définir KIVY_HOME=<dossier>

2. Linux et OSX :

exporter KIVY_HOME=<dossier>

Après le changement de KIVY_HOME, le dossier se comportera exactement de la même manière que le dossier par défaut.kivy/ dossier
mentionné ci-dessus.

7.3 Comprendre les jetons de configuration

Tous les jetons de configuration sont expliqués dans le kivy.config module.

44
CHAPITRE

HUIT

APERÇU ARCHITECTURALE

Nous aimerions prendre un moment pour expliquer comment nous avons conçu Kivy du point de vue de l'ingénierie logicielle. C'est la clé
pour comprendre comment tout fonctionne ensemble. Si vous regardez simplement le code, il y a de fortes chances que vous ayez déjà
une idée approximative, mais comme cette approche est certainement intimidante pour la plupart des utilisateurs, cette section explique
les idées de base de l'implémentation plus en détail. Vous pouvez ignorer cette section et vous y référer plus tard, mais nous vous
suggérons au moins de la parcourir pour un aperçu approximatif.

Kivy se compose de plusieurs blocs de construction que nous expliquerons sous peu. Voici un résumé graphique de
l'architecture :

45
8.1 Fournisseurs principaux et fournisseurs d'intrants

Une idée clé pour comprendre les internes de Kivy est celle de la modularité et de l'abstraction. Nous essayons d'abstraire les
tâches de base telles que l'ouverture d'une fenêtre, l'affichage d'images et de texte, la lecture audio, l'obtention d'images à
partir d'un appareil photo, la correction orthographique, etc. Nous appelons cescoeur Tâches. Cela rend l'API à la fois facile à
utiliser et facile à étendre. Plus important encore, cela nous permet d'utiliser - ce que nous appelons - des fournisseurs
spécifiques pour les scénarios respectifs dans lesquels votre application est exécutée. Par exemple, sur OSX, Linux et Windows, il
existe différentes API natives pour les différentes tâches principales. Un morceau de code qui utilise l'une de ces API spécifiques
pour communiquer avec le système d'exploitation d'un côté et avec Kivy de l'autre (agissant comme une couche de
communication intermédiaire) est ce que nous appelons unfournisseur principal. L'avantage d'utiliser des fournisseurs
principaux spécialisés pour chaque plate-forme est que nous pouvons tirer pleinement parti des fonctionnalités exposées par le
système d'exploitation et agir aussi efficacement que possible. Cela donne également le choix aux utilisateurs. De plus, en
utilisant des bibliothèques livrées avec n'importe quelle plate-forme, nous réduisons efficacement la taille de la distribution Kivy
et facilitons l'empaquetage. Cela facilite également le portage de Kivy sur d'autres plates-formes. Le port Android en a
grandement profité.

Nous suivons le même concept avec la gestion des entrées. Un fournisseur d'intrants est un morceau de code qui ajoute la prise en
charge d'un périphérique d'entrée spécifique, tel que les trackpads d'Apple, TUIO ou un émulateur de souris. Si vous devez ajouter la
prise en charge d'un nouveau périphérique d'entrée, vous pouvez simplement fournir une nouvelle classe qui lit vos données d'entrée à
partir de votre périphérique et les transforme en événements de base Kivy.

8.2 Graphiques

L'API graphique de Kivy est notre abstraction d'OpenGL. Au niveau le plus bas, Kivy émet des commandes de dessin accélérées
par matériel à l'aide d'OpenGL. Écrire du code OpenGL peut cependant être un peu déroutant, en particulier pour les nouveaux
arrivants. C'est pourquoi nous fournissons l'API graphique qui vous permet de dessiner des choses en utilisant des métaphores
simples qui n'existent pas en tant que telles dans OpenGL (par exemple Canvas, Rectangle, etc.).

Tous nos widgets eux-mêmes utilisent cette API graphique, qui est implémentée au niveau C pour des raisons de
performances.

Un autre avantage de l'API graphique est sa capacité à optimiser automatiquement les commandes de dessin émises
par votre code. Ceci est particulièrement utile si vous n'êtes pas un expert dans le réglage d'OpenGL. Cela rend votre
code de dessin plus efficace dans de nombreux cas.

Vous pouvez, bien sûr, toujours utiliser des commandes OpenGL brutes si vous préférez. La version que nous ciblons est OpenGL 2.0 ES
(GLES2) sur tous les appareils, donc si vous souhaitez rester compatible multiplateforme, nous vous conseillons de n'utiliser que les
fonctions GLES2.

8.3 Noyau

Le code du package de base fournit des fonctionnalités couramment utilisées, telles que :

Horloge Vous pouvez utiliser l'horloge pour programmer des événements de minuterie. Les minuteries à un coup et périodiques
les minuteries sont prises en charge.

Cacher Si vous avez besoin de mettre en cache quelque chose que vous utilisez souvent, vous pouvez utiliser notre classe pour cela

au lieu d'écrire le vôtre.


Détection de gestes Nous livrons un simple outil de reconnaissance de gestes que vous pouvez utiliser pour détecter les vari-
différents types de traits, tels que des cercles ou des rectangles. Vous pouvez l'entraîner à détecter vos propres
coups.

Langue Kivy Le langage kivy est utilisé pour décrire facilement et efficacement les interfaces utilisateur.

46
Propriétés Ce ne sont pas les propriétés normales que vous connaissez peut-être de python. Ils sont
nos propres classes de propriétés qui lient le code de votre widget à la description de l'interface utilisateur.

8.4 UIX (Widgets et mises en page)

Le module UIX contient des widgets et des mises en page couramment utilisés que vous pouvez réutiliser pour créer rapidement une
interface utilisateur.

Widgets Les widgets sont des éléments d'interface utilisateur que vous ajoutez à votre programme pour fournir
une sorte de fonctionnalité. Ils peuvent être visibles ou non. Des exemples seraient un navigateur de
fichiers, des boutons, des curseurs, des listes, etc. Les widgets reçoivent des MotionEvents.

Dispositions Vous utilisez des mises en page pour organiser les widgets. Il est bien entendu possible de calculer votre largeur
obtient vous-même les positions, mais il est souvent plus pratique d'utiliser l'une de nos mises en page prêtes à l'emploi. Des exemples

seraient les dispositions de grille ou les dispositions de boîte. Vous pouvez également imbriquer des mises en page.

8.5 Modules

Si vous avez déjà utilisé un navigateur Web moderne et l'avez personnalisé avec des modules complémentaires, vous connaissez déjà
l'idée de base derrière nos classes de modules. Les modules peuvent être utilisés pour injecter des fonctionnalités dans les programmes
Kivy, même si l'auteur original ne les a pas incluses.

Un exemple serait un module qui montre toujours le FPS de l'application actuelle et un graphique décrivant
le FPS au fil du temps.

Vous pouvez également écrire vos propres modules.

8.6 Saisie d'événements (touches)

Kivy extrait différents types et sources d'entrée tels que les touches, les souris, TUIO ou similaires. Ce que tous ces types d'entrée ont en
commun, c'est que vous pouvez associer une position à l'écran 2D à n'importe quel événement d'entrée individuel. (Il existe d'autres
périphériques d'entrée tels que les accéléromètres pour lesquels vous ne pouvez pas facilement trouver une position 2D pour, par
exemple, une inclinaison de votre périphérique. Ce type d'entrée est géré séparément. Dans ce qui suit, nous décrivons les premiers
types.)

Tous ces types d'entrée sont représentés par des instances de la classe Touch(). (Notez que cela ne fait pas seulement référence
au toucher des doigts, mais aussi à tous les autres types d'entrée. Nous venons de l'appelerToucher pour des raisons de
simplicité. Pensez à quelque chose quitouche l'interface utilisateur ou votre écran.) Une instance tactile, ou un objet, peut être
dans l'un des trois états. Lorsqu'un toucher entre dans l'un de ces états, votre programme est informé que l'événement s'est
produit. Les trois états dans lesquels un toucher peut se trouver sont :

Vers le bas Une touche n'est enfoncée qu'une seule fois, au moment même où elle apparaît pour la première fois.

Se déplacer Un toucher peut être dans cet état pendant une durée potentiellement illimitée. Un toucher n'a pas
être dans cet état au cours de sa vie. Un « Move » se produit chaque fois que la position 2D d'un
toucher change.

En haut Une touche monte au plus une fois, ou jamais. En pratique, vous recevrez presque toujours un
up car personne ne va garder un doigt sur l'écran pour l'éternité, mais ce n'est pas
garanti. Si vous connaissez les sources d'entrée que vos utilisateurs utiliseront, vous
saurez si vous pouvez ou non vous fier à cet état.

47
8.7 Widgets et envoi d'événements

Le terme widget est souvent utilisé dans des contextes de programmation GUI pour décrire une partie du programme avec laquelle
l'utilisateur interagit. Dans Kivy, un widget est un objet qui reçoit des événements d'entrée. Il ne doit pas nécessairement avoir une
représentation visible à l'écran. Tous les widgets sont organisés dans unarbre des widgets (qui est une structure de données
arborescente telle qu'elle est connue dans les cours d'informatique) : Un widget peut avoir n'importe quel nombre de widgets enfants ou
aucun. Il y a exactement unwidget racine en haut de l'arborescence qui n'a pas de widget parent, et tous les autres widgets sont
directement ou indirectement des enfants de ce widget (c'est pourquoi on l'appelle la racine).

Lorsque de nouvelles données d'entrée sont disponibles, Kivy envoie un événement par touche. Le widget racine de
l'arborescence des widgets reçoit d'abord l'événement. Selon l'état du toucher, l'événement on_touch_down,
on_touch_move ou on_touch_up est envoyé (avec le toucher comme argument) au widget racine, ce qui entraîne l'appel
du gestionnaire d'événement on_touch_down, on_touch_move ou on_touch_up correspondant du widget racine.

Chaque widget (ceci inclut le widget racine) de l'arborescence peut choisir de digérer ou de transmettre l'événement. Si
un gestionnaire d'événement renvoie True, cela signifie que l'événement a été digéré et géré correctement. Aucun autre
traitement n'aura lieu avec cet événement. Sinon, le gestionnaire d'événements transmet le widget à ses propres
enfants en appelant l'implémentation de sa superclasse du gestionnaire d'événements respectif. Cela va jusqu'à la
classe Widget de base, qui - dans ses gestionnaires d'événements tactiles - ne fait que transmettre les touches à ses
enfants :

# Ceci est analogue pour move/up : déf


on_touch_down(soi, toucher): pour
enfant dans soi.enfants[:] :
si enfant.envoi('on_touch_down', toucher):
retourner vrai

C'est vraiment beaucoup plus facile qu'il n'y paraît au premier abord. Un exemple de la façon dont cela peut être utilisé pour créer
rapidement de belles applications sera donné dans la section suivante.

Souvent, vous voudrez restreindre le région sur l'écran qu'un widget surveille les touches. Vous pouvez utiliser la
méthode collide_point() d'un widget pour y parvenir. Vous lui transmettez simplement la position du toucher et il renvoie
True si le toucher se trouve dans la "zone surveillée" ou False dans le cas contraire. Par défaut, cela vérifie la région
rectangulaire sur l'écran qui est décrite par la position du widget (pour la position ; x et y) et la taille (largeur et hauteur),
mais vous pouvez remplacer ce comportement dans votre propre classe.

48
CHAPITRE

NEUF

ÉVÉNEMENTS ET PROPRIÉTÉS

Les événements sont une partie importante de la programmation Kivy. Cela n'est peut-être pas surprenant pour ceux qui ont de
l'expérience dans le développement d'interfaces graphiques, mais c'est un concept important pour les nouveaux arrivants. Une fois que
vous aurez compris comment fonctionnent les événements et comment vous y lier, vous les verrez partout à Kivy. Ils permettent de créer
facilement le comportement que vous souhaitez dans Kivy.

L'illustration suivante montre comment les événements sont gérés dans le framework Kivy.

Le fil conducteur de Kivy

Saisir
Opérations non GUI qui
Entrée d'expédition peut être reporté à un
Répartiteur d'événements
Événements fil différent.

Événements personnalisés

Événements de propriété

Événements de fenêtre
Système de fichiers

Traitement des entrées

Post-traitement Réseau
(appuyez deux fois, faites glisser, etc.)

Événements de mouvement
Traiter

IHM graphique

Autre

Boucle principale de Kivy


Événements d'horloge

Boucler

49
9.1 Présentation du répartiteur d'événements

L'une des classes de base les plus importantes du framework est la Répartiteur d'événements classer. Cette classe vous
permet d'enregistrer des types d'événements et de les envoyer aux parties intéressées (généralement d'autres répartiteurs
d'événements). leWidget, Animation et Horloge les classes sont des exemples de répartiteurs d'événements.

Les objets EventDispatcher dépendent de la boucle principale pour générer et gérer les événements.

9.2 Boucle principale

Comme indiqué dans l'illustration ci-dessus, Kivy a un boucle principale. Cette boucle s'exécute pendant toute la durée
de vie de l'application et ne se ferme qu'en quittant l'application.

À l'intérieur de la boucle, à chaque itération, des événements sont générés à partir de l'entrée de l'utilisateur, de capteurs matériels ou de
quelques autres sources, et les images sont restituées à l'écran.

Votre application spécifiera des rappels (nous y reviendrons plus tard), qui sont appelés par la boucle principale. Si un rappel
prend trop de temps ou ne se ferme pas du tout, la boucle principale est rompue et votre application ne fonctionne plus
correctement.

Dans les applications Kivy, vous devez éviter les boucles longues/infinies ou le sommeil. Par exemple, le code suivant fait les
deux :

tant que vrai :


animer_quelque chose()
temps.sommeil(.dix)

Lorsque vous exécutez cela, le programme ne quittera jamais votre boucle, empêchant Kivy de faire toutes les autres choses qui
doivent être faites. En conséquence, tout ce que vous verrez est une fenêtre noire avec laquelle vous ne pourrez pas interagir.
Au lieu de cela, vous devez « planifier » votreanimer_quelquechose() fonction à appeler à plusieurs reprises.

9.2.1 Planification d'un événement répétitif

Vous pouvez appeler une fonction ou une méthode toutes les X fois par seconde en utilisant schedule_interval(). Voici un
exemple d'appel d'une fonction nommée my_callback 30 fois par seconde :

déf mon_rappel(dt):
imprimer(« Mon rappel est appelé », dt)
un événement = Horloge.horaire_intervalle(mon_rappel, 1 / 30.)

Vous avez plusieurs façons de déprogrammer un événement déjà programmé. L'un consiste à utiliserAnnuler() ou
déprogrammer() :

un événement.Annuler()

ou:

Horloge.imprévu(un événement)

Alternativement, vous pouvez renvoyer False dans votre rappel, et votre événement sera automatiquement déprogrammé :

=0
compter
déf mon_rappel(dt):
global compter
compter +=1
(suite à la page suivante)

50
(suite de la page précédente)

si compter == dix:
imprimer('Dernier appel de mon rappel, bye bye !') renvoie
Faux
imprimer(« Mon rappel est appelé »)
Horloge.horaire_intervalle(mon_rappel, 1 / 30.)

9.2.2 Planification d'un événement ponctuel

Utilisant schedule_once(), vous pouvez appeler une fonction "plus tard", comme dans l'image suivante, ou dans X secondes :

déf mon_rappel(dt):
imprimer('Mon rappel est appelé !')
Horloge.horaire_une fois(mon_rappel, 1)

Cela appellera mon_rappel en une seconde. Le deuxième argument est le temps d'attente avant d'appeler la
fonction, en secondes. Cependant, vous pouvez obtenir d'autres résultats avec des valeurs spéciales pour le
deuxième argument :

• Si X est supérieur à 0, le rappel sera appelé dans X secondes

• Si X vaut 0, le rappel sera appelé après la trame suivante

• Si X vaut -1, le rappel sera appelé avant la trame suivante

Le -1 est principalement utilisé lorsque vous êtes déjà dans un événement planifié et si vous souhaitez planifier un appel AVANT
que la prochaine image ne se produise.

Une deuxième méthode pour répéter un appel de fonction consiste à programmer d'abord un rappel une fois avec
schedule_once(), et un deuxième appel à cette fonction à l'intérieur du rappel lui-même :

déf mon_rappel(dt):
imprimer('Mon rappel est appelé !')
Horloge.horaire_une fois(mon_rappel, 1)
Horloge.horaire_une fois(mon_rappel, 1)

Alors que la boucle principale essaiera de respecter l'horaire tel que demandé, il existe une certaine incertitude quant au
moment exact où un rappel programmé sera appelé. Parfois, un autre rappel ou une autre tâche dans l'application
prendra plus de temps que prévu et le timing peut donc être un peu décalé.

Dans cette dernière solution au problème de rappel répétitif, l'itération suivante sera appelée au moins une
seconde après la fin de la dernière itération. Avecschedule_interval() cependant, le rappel est appelé toutes les
secondes.

9.2.3 Événements déclencheurs

Parfois, vous souhaiterez peut-être programmer une fonction pour qu'elle ne soit appelée qu'une seule fois pour la trame suivante, évitant ainsi les
appels en double. Vous pourriez être tenté d'y parvenir comme ceci :

# Tout d'abord, programmez une fois.


un événement = Horloge.horaire_une fois(mon_rappel, 0)

# Ensuite, dans un autre endroit, vous devrez d'abord annuler l'horaire


# pour éviter les appels en double. Ensuite, vous pouvez planifier à nouveau.
Horloge.imprévu(un événement)
un événement = Horloge.horaire_une fois(mon_rappel, 0)

51
Cette façon de programmer un déclencheur est coûteuse, car vous appellerez toujours unschedule, même si l'événement est
déjà terminé. De plus, un nouvel événement est créé à chaque fois. Utilisez plutôt un déclencheur :

gâchette = Horloge.create_trigger(mon_rappel)
# plus tard
gâchette()

Chaque fois que vous appelez trigger(), il programmera un seul appel de votre rappel. S'il était déjà programmé, il ne
sera pas reprogrammé.

9.3 Événements de widgets

Un widget a 2 types d'événements par défaut :

• Événement de propriété : si votre widget change de position ou de taille, un événement est déclenché.

• Événement défini par le widget : par exemple, un événement sera déclenché pour un bouton lorsqu'il est enfoncé ou relâché.

Pour une discussion sur la façon dont les événements tactiles de widget sont gérés et propagés, veuillez vous référer à la Widget touch
événement bouillonnant section.

9.4 Création d'événements personnalisés

Pour créer un répartiteur d'événements avec des événements personnalisés, vous devez enregistrer le nom de l'événement
dans la classe, puis créer une méthode du même nom.

Voir l'exemple suivant :

classer MyEventDispatcher(Répartiteur d'événements):


déf __init__(soi, **kwargs):
soi.register_event_type('on_test')
super(MyEventDispatcher, soi).__init__(**kwargs)

déf faire quelque chose(soi, valeur):


# lorsque do_something est appelé, l'événement 'on_test' sera
# expédié avec la valeur soi.envoi(
'on_test', valeur)

déf on_test(soi, *arguments): imprimer("Je


suis expédié", arguments)

9.5 Joindre des rappels

Pour utiliser des événements, vous devez leur lier des rappels. Lorsque l'événement est distribué, vos rappels seront
appelés avec les paramètres relatifs à cet événement spécifique.

Un rappel peut être n'importe quel appel python, mais vous devez vous assurer qu'il accepte les arguments émis par l'événement. Pour
cela, il est généralement plus sûr d'accepter le*arguments argument, qui attrapera tous les arguments dans le arguments liste.

Exemple:

52
déf mon_rappel(valeur, *arguments):
imprimer(« Bonjour, j'ai un événement ! », arguments)

ev = MyEventDispatcher() ev.lier(
on_test=mon_rappel) ev.faire quelque
chose('test')

Veuillez vous référer au kivy.event.EventDispatcher.bind() documentation de la méthode pour plus d'exemples sur la
façon d'attacher des rappels.

9.6 Présentation des propriétés

Les propriétés sont un excellent moyen de définir des événements et de s'y lier. Essentiellement, ils produisent des événements
tels que lorsqu'un attribut de votre objet change, toutes les propriétés qui font référence à cet attribut sont automatiquement
mises à jour.

Il existe différents types de propriétés pour décrire le type de données que vous souhaitez gérer.

• Propriété de chaîne
• Propriété numérique
• Propriété numérique bornée
• Propriété de l'objet
• Propriété Dict
• Propriété de liste
• OptionPropriété
• AliasPropriété
• Propriété booléenne
• ReferenceListProperty

9.7 Déclaration d'une propriété

Pour déclarer des propriétés, vous devez les déclarer au niveau de la classe. La classe fera ensuite le travail pour
instancier les vrais attributs lorsque votre objet sera créé. Ces propriétés ne sont pas des attributs : ce sont des
mécanismes de création d'événements basés sur vos attributs :

classer MonWidget(Widget):

texte = Propriété de chaîne('')

Lors de la substitution __init__, toujours J'accepte **kwargs et utilise super() appeler le parent __init__ méthode, en
passant votre instance de classe :

déf __init__(soi, **kwargs):


super(MonWidget, soi).__init__(**kwargs)

53
9.8 Envoi d'un événement Propriété

Les propriétés Kivy, par défaut, fournissent un on_<nom_propriété> un événement. Cet événement est appelé lorsque la valeur
de la propriété est modifiée.

Noter: Si la nouvelle valeur de la propriété est égale à la valeur actuelle, alors le on_<nom_propriété> l'événement ne
sera pas appelé.

Par exemple, considérons le code suivant :

1 classer Btn personnalisé(Widget):


2

3 pressé = Propriété de liste([0, 0])


4

5 déf on_touch_down(soi, toucher): si soi.


6 collision_point(*toucher.position):
sept soi.pressé = toucher.position
8 retourner vrai
9 retourner super(Btn personnalisé, soi).on_touch_down(toucher)
dix

11 déf on_pressed(soi, exemple, position):


12 imprimer('appuyé sur {pos}'.format(position=position))

Dans le code ci-dessus à la ligne 3 :

pressé = Propriété de liste([0, 0])

Nous définissons le pressé Propriété de type Propriété de liste, en lui donnant une valeur par défaut de [0, 0]. A partir
de ce point, leon_pressed event sera appelé chaque fois que la valeur de cette propriété est modifiée.

A la ligne 5 :

déf on_touch_down(soi, toucher): si soi.


collision_point(*toucher.position):
soi.pressé = toucher.position
retourner vrai
retourner super(Btn personnalisé, soi).on_touch_down(toucher)

Nous supplantons le on_touch_down() méthode de la classe Widget. Ici, nous vérifions la collision du toucher avec
notre widget.

Si le toucher tombe à l'intérieur de notre widget, nous modifions la valeur de pressé à touch.pos et renvoie True,
indiquant que nous avons consommé le toucher et que nous ne voulons plus qu'il se propage.

Enfin, si le toucher tombe en dehors de notre widget, nous appelons l'événement d'origine en utilisant super(. . . ) et renvoie le résultat.
Cela permet à la propagation de l'événement tactile de se poursuivre comme elle se serait normalement produite.

Enfin à la ligne 11 :

déf on_pressed(soi, exemple, position):


imprimer('appuyé sur {pos}'.format(position=position))

Nous définissons un on_pressed fonction qui sera appelée par la propriété chaque fois que la valeur de la propriété est
modifiée.

Noter: Cette on_<prop_name> event est appelé dans la classe où la propriété est définie. Pour surveiller/observer toute
modification apportée à une propriété en dehors de la classe où elle est définie, vous devez vous lier à la

54
propriété comme indiqué ci-dessous.

Liaison avec la propriété

Comment surveiller les modifications apportées à une propriété lorsque vous n'avez accès qu'à une instance de widget ? Vouslier à la
propriété :

votre_instance_widget.lier(nom de la propriété=nom_fonction)

Par exemple, considérons le code suivant :

1 classer RacineWidget(BoxLayout):
2

3 déf __init__(soi, **kwargs):


4 super(RacineWidget, soi).__init__(**kwargs) soi.
5 1'))
add_widget(Bouton(texte='btn cb = Btn personnalisé()
6

sept cb.lier(pressé=soi.btn_pressed) soi.


8 add_widget(cb)
9 soi.add_widget(Bouton(texte='btn 2'))
dix

11 déf btn_pressed(soi, exemple, position):


12 imprimer(« pos : imprimé à partir du widget racine : {pos} ».format(position=.position))

Si vous exécutez le code tel quel, vous remarquerez deux instructions print dans la console. Un duon_pressed
événement qui est appelé à l'intérieur du Btn personnalisé classe et un autre de la btn_pressed fonction que nous lions
au changement de propriété.

La raison pour laquelle les deux fonctions sont appelées est simple. Lier ne veut pas dire écraser. Avoir ces deux
fonctions est redondant et vous ne devez généralement utiliser qu'une des méthodes d'écoute/réaction aux
changements de propriété.

Vous devez également prendre note des paramètres qui sont passés au on_<nom_propriété> événement ou la
fonction liée à la propriété.

déf btn_pressed(soi, exemple, position):

Le premier paramètre est soi, qui est l'instance de la classe où cette fonction est définie. Vous pouvez utiliser une
fonction en ligne comme suit :

1 cb = Btn personnalisé()
2

3 déf _local_func(exemple, position):


4 imprimer(« pos : imprimé à partir du widget racine : {pos} ».format(position=position))
5

6 cb.lier(pressé=_local_func) soi.
sept add_widget(cb)

Le premier paramètre serait le exemple de la classe la propriété est définie.

Le deuxième paramètre serait le valeur, qui est la nouvelle valeur de la propriété.

Voici l'exemple complet, dérivé des extraits ci-dessus, que vous pouvez utiliser pour copier et coller dans un
éditeur pour expérimenter.

1 à partir de kivy.app importer Application à partir


2 de kivy.uix.widget importer Widget à partir de
3 bouton kivy.uix importer Bouton
(suite à la page suivante)

55
(suite de la page précédente)

4 à partir de kivy.uix.boxlayout importer BoxLayout à


5 partir de kivy.properties importer Propriété de liste
6

sept classer RacineWidget(BoxLayout):


8

9 déf __init__(soi, **kwargs):


dix super(RacineWidget, soi).__init__(**kwargs) soi.
11 1'))
add_widget(Bouton(texte='btn cb = Btn personnalisé()
12

13 cb.lier(pressé=soi.btn_pressed) soi.
14 add_widget(cb)
15 soi.add_widget(Bouton(texte='btn 2'))
16

17 déf btn_pressed(soi, exemple, position):


18 imprimer(« pos : imprimé à partir du widget racine : {pos} ».format(position=position))
19

20 classer Btn personnalisé(Widget):


21

22 pressé = Propriété de liste([0, 0])


23

24 déf on_touch_down(soi, toucher): si soi.


25 collision_point(*toucher.position):
26 soi.pressé = toucher.position
27 # nous avons consommé le toucher. retourner False ici pour se propager
28 # le toucher plus loin aux enfants. retourner
29 vrai
30 retourner super(Btn personnalisé, soi).on_touch_down(toucher)
31

32 déf on_pressed(soi, exemple, position):


33 imprimer('appuyé sur {pos}'.format(position=position))
34

35 classer Application de test(Application):

36

37 déf construire(soi):
38 retourner RacineWidget()
39

40

41 si __Nom__ == '__principale__':
42 Application de test().Cours()

L'exécution du code ci-dessus vous donnera le résultat suivant :

56
Notre CustomBtn n'a pas de représentation visuelle et apparaît donc en noir. Vous pouvez toucher/cliquer sur la zone
noire pour voir la sortie sur votre console.

9.9 Propriétés du composé

Lors de la définition d'un AliasPropriété, vous définissez normalement vous-même une fonction getter et setter. Ici, il
vous appartient de définir quand les fonctions getter et setter sont appelées à l'aide de lalier argument.

Considérez le code suivant.

1 curseur_pos = AliasPropriété(_get_cursor_pos, Rien,


2 lier=('le curseur', 'rembourrage', 'pos', 'Taille',
3 'concentrer', 'scroll_x', 'scroll_y', 'hauteur de
4 la ligne', 'interligne'), cache=Vrai)
5

6 '''Position actuelle du curseur, en (x, y).


sept

8 :attr:`cursor_pos` est une :class:`~kivy.properties.AliasProperty`, en lecture seule.


9

dix '''

Ici curseur_pos est un AliasPropriété qui utilise le getter _get_cursor_pos avec le setter partie définie sur Aucun, ce qui implique
qu'il s'agit d'une propriété en lecture seule.

L'argument bind à la fin définit que on_cursor_pos l'événement est distribué lorsque l'une des propriétés utilisées dans
le lier = changement d'argumentation.

57
58
CHAPITRE

DIX

GESTION DES ENTRÉES

10.1 Architecture d'entrée

Kivy est capable de gérer la plupart des types de saisie : souris, écran tactile, accéléromètre, gyroscope, etc. Il
gère les protocoles multitouch natifs sur les plateformes suivantes : Tuio, WM_Touch, MacMultitouchSupport, MT
Protocol A/B et Android.

L'architecture globale peut être vue comme :

Fournisseurs d'intrants -> Événement de mouvement -> Post-traitement -> Envoi à la fenêtre

La classe de tous les événements d'entrée est la Événement de mouvement. Il génère 2 types d'événements :

• Événements tactiles : un événement de mouvement qui contient au moins une position X et Y. Tous les événements tactiles sont
répartis dans l'arborescence des widgets.

• Événements sans contact : tout le reste. Par exemple, l'accéléromètre est un événement continu, sans position. Il ne
démarre ni ne s'arrête jamais. Ces événements ne sont pas distribués dans l'arborescence des widgets.

Un événement de mouvement est généré par un Fournisseur d'entrée. Un fournisseur d'entrée est chargé de lire l'événement
d'entrée à partir du système d'exploitation, du réseau ou même d'une autre application. Plusieurs fournisseurs d'intrants
existent, tels que :

• TuioMotionEventProvider: créer un serveur UDP et écouter les messages TUIO/OSC.


• WM_MotionEventProvider : utilisez l'API Windows pour lire les informations multitouch et les
envoyer à Kivy.
• ProbeSysfsHardwareProbe : Sous Linux, itérez sur tout le matériel connecté à l'ordinateur et associez un
fournisseur d'entrée multitouch pour chaque périphérique multitouch trouvé.

• et beaucoup plus!

Lorsque vous écrivez une application, vous n'avez pas besoin de créer un fournisseur d'entrée. Kivy essaie de détecter
automatiquement le matériel disponible. Cependant, si vous souhaitez prendre en charge du matériel personnalisé, vous devrez
configurer kivy pour le faire fonctionner.

Avant que l'événement de mouvement nouvellement créé ne soit transmis à l'utilisateur, Kivy applique un post-traitement à l'entrée.
Chaque événement de mouvement est analysé pour détecter et corriger les entrées défectueuses, ainsi que pour faire des
interprétations significatives telles que :

• Détection double/triple pression, selon un seuil de distance et de temps

• Rendre les événements plus précis lorsque le matériel n'est pas précis

• Réduction du nombre d'événements générés si le matériel tactile natif envoie des événements avec presque
la même position

Après le traitement, l'événement de mouvement est envoyé à la fenêtre. Comme expliqué précédemment, tous les événements ne sont
pas distribués à l'ensemble de l'arborescence des widgets : la fenêtre les filtre. Pour un événement donné :

59
• s'il ne s'agit que d'un événement de mouvement, il sera envoyé à on_motion()

• s'il s'agit d'un événement tactile, la position (x,y) du toucher (plage 0-1) sera mise à l'échelle de la taille de la fenêtre
(largeur/hauteur) et envoyée à :

– on_touch_down()
– on_touch_move()
– on_touch_up()

10.2 Profils d'événements de mouvement

En fonction de votre matériel et des fournisseurs d'entrées utilisés, plus d'informations peuvent être mises à votre disposition.
Par exemple, une entrée tactile a une position (x,y), mais peut également avoir des informations sur la pression, la taille du blob,
un vecteur d'accélération, etc.

Un profil est une chaîne qui indique les fonctionnalités disponibles dans l'événement de mouvement. Imaginons que
vous soyez dans unon_touch_move méthode:

déf on_touch_move(soi, toucher):


imprimer(toucher.profil)
retourner super(..., soi).on_touch_move(toucher)

L'impression pourrait sortir :

['pos', 'angle']

Avertissement: De nombreuses personnes confondent le nom du profil et le nom de la propriété correspondante.


Juste parce que 'angle' est dans le profil disponible ne signifie pas que l'objet d'événement tactile aura un angle
propriété.

Pour le 'pos' profil, les propriétés position, x, et oui sera disponible. Avec le 'angle' profil, la propriété une sera
disponible. Comme nous l'avons dit, pour les événements tactiles 'pos' est un profil obligatoire, mais pas 'angle'.
Vous pouvez prolonger votre interaction en vérifiant si le 'angle' le profil existe :

déf on_touch_move(soi, toucher):


imprimer(« Le toucher est en position », toucher.position)
si 'angle' dans toucher.profil:
imprimer(« L'angle de contact est », toucher.une)

Vous pouvez trouver une liste des profils disponibles dans le événement de mouvement Documentation.

10.3 Événements tactiles

Un événement tactile est un événement spécialisé Événement de mouvement où la propriété is_touch évalue à True. Pour
tous les événements tactiles, vous disposez automatiquement des positions X et Y, adaptées à la largeur et à la hauteur de la
fenêtre. En d'autres termes, tous les événements tactiles ont le 'pos' profil.

60
10.3.1 Principes de base des événements tactiles

Par défaut, les événements tactiles sont envoyés à tous les widgets actuellement affichés. Cela signifie que les widgets reçoivent
l'événement tactile, qu'il se produise ou non dans leur zone physique.

Cela peut être contre-intuitif si vous avez de l'expérience avec d'autres boîtes à outils GUI. Ceux-ci divisent généralement l'écran
en zones géométriques et n'envoient des événements tactiles ou de souris au widget que si la coordonnée se trouve dans la
zone des widgets.

Cette exigence devient très restrictive lorsque l'on travaille avec la saisie tactile. Les balayages, les
pincements et les appuis longs peuvent provenir de l'extérieur du widget qui veut les connaître et y réagir.

Afin de fournir une flexibilité maximale, Kivy distribue les événements à tous les widgets et leur permet de décider comment y
réagir. Si vous souhaitez uniquement répondre aux événements tactiles à l'intérieur du widget, il vous suffit de cocher :

déf on_touch_down(soi, toucher): si soi.


collision_point(*toucher.position):
# Le toucher s'est produit à l'intérieur de la zone des widgets. Faire des choses!
passe

10.3.2 Coordonnées

Vous devez vous occuper de la transformation matricielle dans votre toucher dès que vous utilisez un widget avec
transformation matricielle. Certains widgets tels queDispersion ont leur propre transformation matricielle, ce qui signifie que le
toucher doit être multiplié par la matrice de dispersion pour pouvoir distribuer correctement les positions tactiles aux enfants
du Scatter.

• Obtenir les coordonnées de l'espace parent vers l'espace local : to_local()

• Obtenir les coordonnées de l'espace local vers l'espace parent : à_parent()

• Obtenir les coordonnées de l'espace local vers l'espace de la fenêtre : à_fenêtre()

• Obtenir les coordonnées de l'espace fenêtre vers l'espace local : to_widget()

Vous devez utiliser l'un d'eux pour mettre correctement les coordonnées à l'échelle du contexte. Regardons l'implémentation du scatter :

déf on_touch_down(soi, toucher):


# pousser la coordonnée courante, pour pouvoir la restaurer plus tard
toucher.pousser()

# transformer la coordonnée tactile en espace local toucher.


appliquer_transformer_2d(soi.à_local)

# expédier le toucher comme d'habitude aux enfants


# la coordonnée au toucher est maintenant dans l'espace local
ret = super(..., soi).on_touch_down(toucher)

# quel que soit le résultat, n'oubliez pas de faire éclater votre transformation
# après l'appel, donc la coordonnée sera de retour dans l'espace parent toucher.
pop()

# renvoie le résultat (selon ce que vous voulez.) retourner


ret

61
10.3.3 Formes tactiles

Si le toucher a une forme, cela sera reflété dans la propriété 'shape'. À l'heure actuelle, seul unFormeRect peut être
exposé :

à partir de kivy.input.shape importer FormeRect

déf on_touch_move(soi, toucher):


si isinstance(toucher.forme, FormeRect):
imprimer('Mon toucher a une forme de rectangle de taille',
(toucher.forme.largeur, toucher.forme.la taille))
#...

10.3.4 Appuyez deux fois

Un double tap est l'action de tapoter deux fois dans un temps et une distance. Il est calculé par le module de post-
traitement doubletap. Vous pouvez tester si le toucher actuel est celui d'un double tap ou non :

déf on_touch_down(soi, toucher): si


toucher.is_double_tap:
imprimer('Le toucher est un double tap !')
imprimer(' - l'intervalle est', toucher.double_tap_time)
imprimer(' - la distance entre le précédent est', toucher.double_tap_distance)
#...

10.3.5 Appuyez trois fois

Un triple tap est l'action de tapoter trois fois dans un temps et une distance. Il est calculé par le module de post-
traitement tripletap. Vous pouvez tester si le toucher actuel est l'un d'un triple tap ou non :

déf on_touch_down(soi, toucher): si


toucher.is_triple_tap:
imprimer(« Le toucher est un triple tapotement ! »)
imprimer(' - l'intervalle est', toucher.triple_tap_time)
imprimer(' - la distance entre le précédent est', toucher.triple_tap_distance)
#...

10.3.6 Saisie d'événements tactiles

Il est possible pour le widget parent d'envoyer un événement tactile à un widget enfant depuis l'intérieur
on_touch_down, mais pas de on_touch_move ou on_touch_up. Cela peut se produire dans certains scénarios, comme
lorsqu'un mouvement tactile est en dehors de la zone de délimitation du parent, de sorte que le parent décide de ne pas
informer ses enfants du mouvement.

Mais vous voudrez peut-être faire quelque chose dans on_touch_up. Disons que vous avez commencé quelque chose dans le

on_touch_down événement, comme jouer un son, et vous aimeriez finir les choses sur le on_touch_up un événement.
Saisir est ce dont vous avez besoin.

Lorsque vous saisissez une touche, vous recevrez toujours l'événement de déplacement et de montée. Mais il y a certaines
limites à la saisie :

• Vous recevrez l'événement au moins deux fois : une fois de votre parent (l'événement normal), et une
fois de la fenêtre (saisir).

62
• Vous pouvez recevoir un événement avec un toucher saisi, mais pas de vous : cela peut être dû au fait que le parent
a envoyé le toucher à ses enfants alors qu'il était dans l'état saisi.

Voici un exemple d'utilisation de la saisie :

déf on_touch_down(soi, toucher): si soi.


collision_point(*toucher.position):

# si le toucher entre en collision avec notre widget, saisissons-le


toucher.attraper(soi)

# et acceptez le toucher.
retourner vrai

déf on_touch_up(soi, toucher):


# ici, vous ne vérifiez pas si le toucher entre en collision ou des choses comme ça.
# il vous suffit de vérifier s'il s'agit d'un événement tactile saisi si
toucher.saisir_courant est soi:

# ok, la touche actuelle est expédiée pour nous.


# faites quelque chose d'intéressant ici
imprimer('Bonjour le monde!')

# n'oubliez pas de vous défaire, ou vous pourriez avoir des effets secondaires
toucher.dégager(soi)

# et accepter le dernier up
retourner vrai

10.3.7 Gestion des événements tactiles

Afin de voir comment les événements tactiles sont contrôlés et propagés entre les widgets, veuillez vous référer à la Widget
touch événement bouillonnant section.

10.4 Événements de manette

Une entrée de joystick représente les valeurs brutes reçues directement des contrôleurs physiques ou virtuels via le fournisseur
SDL2 via ces événements :

• SDL_JOYAXISMOTION
• SDL_JOYHATMOTION
• SDL_JOYBALLMOTION
• SDL_JOYBUTTONDOWN
• SDL_JOYBUTTONUP
Chaque événement de mouvement a une valeur minimale, maximale et par défaut qui peut atteindre :

Événement Le minimum Maximum Défaut


on_joy_axis - 32767 32767 0
on_joy_hat (-1, -1) (1, 1) (0, 0)
on_joy_ball Inconnue Inconnue Inconnue

63
Les événements de bouton, d'autre part, ne représentent fondamentalement qu'un état de chaque bouton, c'est-à-dire en haut et vers le bas, par conséquent,

aucune de ces valeurs n'est présente.

• on_joy_button_up
• on_joy_button_down

10.4.1 Principes de base des événements du joystick

Contrairement aux événements tactiles, les événements de joystick sont envoyés directement à la fenêtre, ce qui signifie qu'il n'y a qu'une
seule valeur transmise pour, par exemple, un axe spécifié, pas plusieurs. Cela rend les choses plus difficiles si vous souhaitez séparer les
entrées de différents widgets, mais pas impossible. Vous pouvez utiliserExemple de dropfile multiple comme inspiration.

Pour obtenir un événement joystick, vous devez d'abord lier une fonction à l'événement Window joystick comme ceci :

Fenêtre.lier(on_joy_axis=soi.on_joy_axis)

Ensuite, vous devez récupérer les paramètres spécifiés dans Fenêtre pour chaque événement que vous utilisez, par exemple :

déf on_joy_axis(soi, gagner, collant, axe, valeur):


imprimer(gagner, collant, axe, valeur)

Une variable collant est l'identifiant d'un contrôleur qui a envoyé la valeur, axe est l'identifiant d'un axe auquel appartient la
valeur.

10.4.2 Saisie par manette

Kivy devrait pouvoir récupérer les entrées de n'importe quel appareil spécifié comme manette de jeu, manette ou
essentiellement tout autre type de contrôleur de jeu reconnu par le fournisseur SDL2. Pour faciliter les choses, voici les
dispositions de certains contrôleurs courants ainsi que les identifiants de chaque partie.

64
Xbox 360

# identifiant # identifiant

1 axe 1 2 axe 0
3 chapeau Y 4 chapeau X

5 axe 4 6 axe 3
sept axe 2 8 axe 5
9 bouton 4 dix bouton 5
X bouton 2 Oui bouton 3
UNE bouton 0 B bouton 1
retour bouton 6 début bouton 7
centre bouton 10

10.4.3 Débogage du joystick

La plupart du temps, vous voudriez déboguer votre application avec plusieurs contrôleurs ou la tester par rapport à _autres_
types de contrôleurs (par exemple, différentes marques). Comme alternative, vous pouvez utiliser certains des émulateurs de
contrôleur disponibles, tels quevJoy.

65
66
CHAPITRE

ONZE

WIDGETS

11.1 Présentation des widgets

UNE Widget est le bloc de construction de base des interfaces graphiques dans Kivy. Il fournit unToile qui peut être
utilisé pour dessiner à l'écran. Il reçoit les événements et y réagit. Pour une explication détaillée de laWidget classe,
consultez la documentation du module.

11.2 Manipulation de l'arborescence des widgets

Les widgets à Kivy sont organisés en arbres. Votre candidature a unwidget racine, qui a généralement enfants
qui peut avoir enfants de leur propre. Les enfants d'un widget sont représentés par leenfants attribut, un Kivy
Propriété de liste.

L'arborescence des widgets peut être manipulée avec les méthodes suivantes :

• add_widget(): ajouter un widget en tant qu'enfant

• remove_widget(): supprimer un widget de la liste des enfants


• clear_widgets(): supprimer tous les enfants d'un widget
Par exemple, si vous souhaitez ajouter un bouton à l'intérieur d'un BoxLayout, vous pouvez faire :

disposition = BoxLayout(rembourrage=dix) bouton =


Bouton(texte='Mon premier bouton') disposition.
add_widget(bouton)

Le bouton est ajouté à layout : la propriété parent du bouton sera définie sur layout ; la mise en page aura le
bouton ajouté à sa liste d'enfants. Pour supprimer le bouton de la mise en page :

disposition.supprimer_widget(bouton)

Avec la suppression, la propriété parent du bouton sera définie sur Aucun et la mise en page aura le bouton supprimé
de sa liste d'enfants.

Si vous souhaitez effacer tous les enfants à l'intérieur d'un widget, utilisez clear_widgets() méthode:

disposition.clear_widgets()

Avertissement: Ne manipulez jamais vous-même la liste des enfants, à moins que vous ne sachiez vraiment ce que vous
faites. L'arbre des widgets est associé à un arbre graphique. Par exemple, si vous ajoutez un widget dans le

67
liste des enfants sans ajouter son canevas à l'arborescence graphique, le widget sera un enfant, oui, mais rien
ne sera dessiné à l'écran. De plus, vous pourriez avoir des problèmes lors d'appels ultérieurs de add_widget,
remove_widget et clear_widgets.

11.3 Traversée de l'arbre

L'instance de la classe Widget enfants La propriété list contient tous les enfants. Vous pouvez facilement parcourir
l'arbre en faisant :

racine = BoxLayout()
# . . . ajouter des widgets à la racine ...
pour enfant dans racine.enfants:
imprimer(enfant)

Cependant, cela doit être utilisé avec précaution. Si vous avez l'intention de modifier la liste des enfants avec l'une des méthodes
indiquées dans la section précédente, vous devez utiliser une copie de la liste comme celle-ci :

pour enfant dans racine.enfants[:] :


# manipuler l'arbre. Par exemple ici, supprimez tous les widgets qui ont un
# largeur < 100
si enfant.largeur < 100:
racine.supprimer_widget(enfant)

Les widgets n'influencent pas la taille/la position de leurs enfants par défaut. leposition l'attribut est la position absolue dans les
coordonnées de l'écran (à moins que vous n'utilisiez le Disposition relative. Plus à ce sujet plus tard) etTaille, est une taille
absolue.

11.4 Indice Z des widgets

L'ordre de dessin des widgets est basé sur la position du widget dans l'arborescence des widgets. leadd_widget méthode prend
un indice paramètre qui peut être utilisé pour spécifier sa position dans l'arborescence des widgets :

racine.add_widget(widget, indice)

Les widgets les moins indexés seront dessinés au-dessus de ceux avec un index plus élevé. Gardez à l'esprit que la valeur par
défaut pourindice est 0, donc les widgets ajoutés plus tard sont dessinés au-dessus des autres, sauf indication contraire.

11.5 Organiser avec des mises en page

disposition est un type spécial de widget qui contrôle la taille et la position de ses enfants. Il existe différents types de
mises en page, permettant une organisation automatique différente de leurs enfants. Utilisation des mises en page
size_hint et pos_hint propriétés pour déterminer la Taille et position de leur enfants.

BoxLayout: organise les widgets de manière adjacente (soit verticalement, soit horizontalement), pour remplir tout l'espace. La
propriété size_hint des enfants peut être utilisée pour modifier les proportions autorisées pour chaque enfant ou définir une
taille fixe pour certains d'entre eux.

68
69
Disposition de la grille: organise les widgets dans une grille. Vous devez spécifier au moins une dimension de la grille pour que
kivy puisse calculer la taille des éléments et comment les organiser.

StackLayout: organise les widgets les uns à côté des autres, mais avec une taille définie dans l'une des
dimensions, sans essayer de les faire tenir dans tout l'espace. Ceci est utile pour afficher les enfants de la même
taille prédéfinie.

AncreLayout: Une mise en page simple ne se souciant que des positions des enfants. Il permet de placer les enfants à une
position relative à une bordure de la mise en page.size_hint n'est pas honoré.

Mise en page flottante: permet de placer des enfants avec des emplacements et des tailles arbitraires, absolus ou relatifs à la taille de la
mise en page. Par défaut size_hint (1, 1) fera que chaque enfant aura la même taille que l'ensemble de la mise en page, vous voudrez
donc probablement modifier cette valeur si vous avez plus d'un enfant. Vous pouvez définir size_hint sur (Aucun, Aucun) pour utiliser la
taille absolue avecTaille. Ce widget honorepos_hint aussi, qui en tant que position de réglage de dict par rapport à la position de mise en
page.

Disposition relative: se comporte comme FloatLayout, sauf que les positions des enfants sont relatives à la position de la disposition, pas
à l'écran.

Examinez la documentation des mises en page individuelles pour une compréhension plus approfondie.

70
size_hint et pos_hint:
• floatlayout
• mise en page
• disposition de la grille

• disposition de la pile

• Disposition relative
• disposition d'ancrage

size_hint est un ReferenceListProperty de size_hint_x et size_hint_y. Il accepte les valeurs de0 à 1 ou Rien et
par défaut à (1, 1). Cela signifie que si le widget est dans une mise en page, la mise en page lui allouera autant de
place que possible dans les deux sens (par rapport à la taille des mises en page).

Réglage size_hint à (0.5, 0.8), par exemple, fera du widget 50% la largeur et 80% la hauteur de la taille disponible
pour le Widget à l'intérieur d'un disposition.

Considérez l'exemple suivant :

BoxLayout:
Bouton:
texte: 'Bouton 1'
# size_hint par défaut est 1, 1, nous n'avons pas besoin de le spécifier explicitement
# cependant c'est fourni ici pour clarifier les choses size_hint: 1
,1

Chargez maintenant le catalogue kivy en tapant ce qui suit, mais en remplaçant $KIVYDIR par le répertoire
de votre installation (découvrable via os.path.dirname(kivy.__file__)):

cd $KIVYDIR/examples/demo/kivycatalog python
main.py

Une nouvelle fenêtre apparaîtra. Cliquez dans la zone en dessous du 'Bienvenue'Fileur sur la gauche et
remplacez le texte par votre code kv ci-dessus.

71
Comme vous pouvez le voir sur l'image ci-dessus, le Bouton occupe 100% de la mise en page Taille.

Changer le size_hint_x/size_hint_y à .5 fera le Widget prendre 50% de la largeur de mise en page/


la taille.

72
Vous pouvez voir ici que, bien que nous précisions size_hint_x et size_hint_y les deux à 0,5, seulement
size_hint_y semble honoré. C'est parce quemise en page contrôle le size_hint_y lorsque orientation est
verticale et size_hint_x lorsque orientation est "horizontal". La taille de la dimension contrôlée est calculée
en fonction du nombre total. deenfants dans le mise en page. Dans cet exemple, un enfant asize_hint_y
contrôlé (.5/.5 = 1). Ainsi, le widget prend 100% de la hauteur de la mise en page parent.

Ajoutons-en un autre Bouton à la disposition et voir ce qui se passe.

73
mise en page par sa nature même divise l'espace disponible entre ses enfants également. Dans notre exemple,
la proportion est de 50-50, car nous avons deuxenfants. Utilisons size_hint sur l'un des enfants et voyons les
résultats.

74
Si un enfant spécifie size_hint, cela spécifie combien d’espace le Widget va prendre de la taille qui lui
_hint
est donnée par la boxlayout. Dans notre exemple, le premier bouton indique . 5 pour size _x.
L’espace pour le widget est calculé comme ceci :
divisé par
Indice de taille du premier enfant
du
size_hint premier enfant + size_hint du deuxième enfant + ...n(aucun enfant)
.5/(.5+1) = .333...

Le reste de la largeur du BoxLayout est réparti entre les autres enfants. Dans notre exemple,
cela signifie que le deuxième bouton occupe 66,66% de la largeur de la mise en page.
_
Expérimentez avec size hint pour être à l’aise avec elle.
Si vous voulez contrôler la taille absolue d’un Widget, vous pouvez définir size_hint_x/size_hint_y
ou les deux à None pour que les attributs width et ou height du widget soient honorés.
_ _hint
pos hint est un dict, qui se vide par défaut. Comme pour size , les mises en page honorent
pos_hint différemment, mais généralement vous pouvez ajouter des valeurs à n’importe lequel des
_x, center Widget
attributs pos (x, y, right, top, center _y) pour que le soit positionné par rapport
à son parent.
_
Expérimentons le code suivant dans kivycatalog pour comprendre pos hint visuellement :
FloatLayout :
Bouton :
texte : « We Will »
pos : 100, 100
_
size hint : . 2, . 4
Bouton :
(suite à la page suivante)

75
(suite de la page précédente)
text: "Wee Wiill"
pos : 200, 200
_
size hint : . 4, . 2
Bouton :
texte : « ROCK YOU! »
_
pos hint : {'x' : . 3, 'y' : . 6}
_
size hint : . 5, . 2
Cela nous donne :

_hint
Comme avec size , vous devriez expérimenter avec pos_hint pour comprendre l’effet qu’il a
sur les positions du widget.

11.6 Ajout d’un arrière-plan à une mise en page

Une des questions fréquemment posées sur les mises en page est la suivante :

"Comment ajouter une image de fond/couleur/vidéo/... à une mise en page"

De par leur nature, les mises en page n’ont pas de représentation visuelle : elles n’ont pas
d’instructions sur toile par défaut. Cependant, vous pouvez facilement ajouter des instructions canvas
à une instance de mise en page, comme avec l’ajout d’un fond coloré :
En Python :

76
à partir de kivy.graphics importer couleur, rectangle
instance.canvas.before
avec layout_ :
Couleur(0, 1, 0, 1) # vert; gamme de couleurs de 0-1 au lieu de 0-255 self.rect =
instance.size,
Rectangle(size=layout_
_
pos=layout instance.pos)
Malheureusement, cela ne dessinera qu’un rectangle à la position et à la taille initiales de la mise en
page. Pour s’assurer que le rect est dessiné à l’intérieur de la mise en page, lorsque la taille de la
mise en page / pos change, nous devons écouter les changements et mettre à jour la taille des
rectangles et pos. Nous pouvons procéder comme suit :
instance.canvas.before
avec layout_ :
Couleur(0, 1, 0, 1) # vert; gamme de couleurs de 0-1 au lieu de 0-255 self.rect =
instance.size,
Rectangle(size=layout_
_
pos=layout instance.pos)
_
def update rect(instance, value) :
instance.rect.pos = instance.pos
instance.rect.size = instance.size

# écouter les changements de taille et de position


_instance.bind
layout (pos=update_rect, size=update_rect)
In kv:

FloatLayout :
avant :
Couleur :
rgba : 0, 1, 0, 1
Rectangle :
# self ici se réfère au widget i.e FloatLayout pos : self.pos

taille : auto.size

La déclaration kv définit une liaison implicite : les deux dernières lignes kv garantissent que les
valeurs pos et size du rectangle seront mises à jour lorsque le pos du floatlayout change.
Maintenant, nous mettons les fragments ci-dessus dans la coquille de Kivy App.
Méthode Python pur :

à partir de l’application d’importation kivy.app


à partir de kivy.graphics importer couleur, rectangle à
partir de kivy.uix.floatlayout importer FloatLayout à
partir de kivy.uix.button importer bouton

classe RootWidget(FloatLayout) :
__ __
def init (self, **kwargs):
# assurez-vous que nous ne surchargeons aucune fonctionnalité
_ __
importante super(RootWidget, self). _init (**kwargs)
# ajoutons un Widget à cette mise en page
_
self.add widget(
Bouton(
(suite à la page suivante)

77
(suite de la page précédente)
text="Hello World",
_
size hint=(.5, .5),
_hint ':
pos ={'center_x . 5, 'center_y' : . 5})

class MainApp(App) :

def build(self) :
self.root = root = RootWidget()
update_rect, pos=self. )
root.bind(size=self._ _update_rect
avec root.canvas.before :
Couleur(0, 1, 0, 1) # vert; gamme de couleurs de 0-1 pas 0-255 self.rect =
Rectangle(size=root.size, pos=root.pos)
racine de retour

_
def update_rect(self, instance, valeur) :
self.rect.pos = instance.pos self.rect.size =
instance.size
_ __ _ __
si _name == ' _main ':
MainApp(). run()

Utilisation de la langue kv :

à partir de l’application d’importation kivy.app


de kivy.lang import Builder

_
root = Builder.load string('''
FloatLayout :
avant :
Couleur :
rgba : 0, 1, 0, 1
Rectangle :
# self ici se réfère au widget i.e FloatLayout pos : self.pos

taille : auto.size
Bouton :
texte : « Bonjour le monde ! »
_
size hint : . 5, . 5
_hint ':. 5, 'center_y' : . 5}
pos : {'center_x
'''')

class MainApp(App) :

def build(self) :
racine de retour
_ __ _ __
si _name == ' _main ':
MainApp(). run()

Les deux applications devraient ressembler à ceci :

78
11.6.1 Ajouter une couleur à l’arrière-plan d’une règle/classe de dispositions
personnalisées

La façon dont nous ajoutons l’arrière-plan à l’instance de la mise en page peut rapidement devenir
lourde si nous avons besoin d’utiliser plusieurs mises en page. Pour vous aider, vous pouvez sous-
classer la mise en page et créer votre propre mise en page qui ajoute un arrière-plan.
Utilisation de Python :

à partir de l’application d’importation kivy.app


from kivy.graphics import Color, Rectangle from
kivy.uix.boxlayout import BoxLayout from
kivy.uix.floatlayout import FloatLayout from
kivy.uix.image import AsyncImage

class RootWidget(BoxLayout) :
passer

Classe CustomLayout (FloatLayout) :


__ __
def init (self, **kwargs):
# assurez-vous que nous ne surchargeons aucune fonctionnalité
_ __
importante super(CustomLayout, self). _init (**kwargs)
(suite à la page suivante)

79
(suite de la page précédente)
avec self.canvas.avant :
Couleur(0, 1, 0, 1) # vert; gamme de couleurs de 0-1 au lieu de 0-
,!255
self.rect = Rectangle(size=self.size, pos=self.pos)

_
self.bind(size=self._update_rect, pos=self. update_rect)
_
def update_rect(self, instance, valeur) :
self.rect.pos = instance.pos self.rect.size =
instance.size

class MainApp(App) :

def build(self) :
root = RootWidget()
c = CustomLayout()
_
root.add widget(c)
_
c.add widget(
AsyncImage(
source="http://www.everythingzoomer.com/wp-content/uploads/
! 2013/01/Monday-joke-289x277.jpg",
_
size hint= (1, .5),
_hint . 5}))
pos ={'center_x':. 5, 'center_y':
_
root.add widget(AsyncImage(source='http://www.stuffistumbledupon.
! com/wp-content/uploads/2012/05/Have-you-seen-this-dog-because-its-,! awesome-
meme-puppy-doggy.jpg'))
c = CustomLayout()
_
c.add widget(
AsyncImage(
source="http://www.stuffistumbledupon.com/wp-content/
,! uploads/2012/04/Get-a-Girlfriend-Meme-empty-wallet.jpg",
_
size hint= (1, .5),
_hint . 5}))
pos ={'center_x':. 5, 'center_y':
_
root.add widget(c)
racine de retour
_ __ _ __
si _name == ' _main ':
MainApp(). run()

Utilisation de la langue kv :

à partir de l’application d’importation kivy.app


from kivy.uix.floatlayout import FloatLayout from
kivy.uix.boxlayout import BoxLayout from kivy.lang
import Builder

_
Builder.load string('''
<CustomLayout>
avant :
Couleur :
rgba : 0, 1, 0, 1
(suite à la page suivante)

80
(suite de la page précédente)
Rectangle :
pos : self.pos
taille : auto.size

<RootWidget>
CustomLayout :
AsyncImage :
source : 'http://www.everythingzoomer.com/wp-content/uploads/
,!2013/01/monday-joke-289x277.jpg'
_
size hint : 1, . 5
_hint ':. 5, 'center_y' : . 5}
pos : {'center_x
AsyncImage :
source : 'http://www.stuffistumbledupon.com/wp-content/uploads/2012/ ,!05/Have-
you-seen-this-dog-because-its-awesome-meme-puppy-doggy.jpg'
CustomLayout
AsyncImage :
source : 'http://www.stuffistumbledupon.com/wp-content/uploads/
,!2012/04/Get-a-Girlfriend-Meme-empty-wallet.jpg'
_
size hint : 1, . 5
_hint ':. 5, 'center_y' : . 5}
pos : {'center_x
'''')

class RootWidget(BoxLayout) :
passer

Classe CustomLayout (FloatLayout) :


passer

class MainApp(App) :

def build(self) :
return RootWidget()
_ __ _ __
si _name == ' _main ':
MainApp(). run()

Les deux applications devraient ressembler à ceci :

81
Définir l’arrière-plan dans la classe de mise en page personnalisée, assure qu’il sera utilisé dans
chaque instance de CustomLayout.
Maintenant, pour ajouter une image ou une couleur à l’arrière-plan d’une mise en page Kivy intégrée,
globalement, nous devons outrepasser la règle kv pour la mise en page en question. Envisager
GridLayout :

<GridLayout>
avant :
Couleur :
rgba : 0, 1, 0, 1
BorderImage :
source : '.. /examples/widgets/sequenced_images/data/images/
_white.png’
,!button
pos : self.pos
taille : auto.size

Puis, lorsque nous avons mis ce fragment dans une application Kivy :

à partir de l’application d’importation kivy.app


à partir de kivy.uix.floatlayout importer FloatLayout à
partir de kivy.lang importer Builder

_
Builder.load string('''
<GridLayout>
avant :
BorderImage :
# BorderImage se comporte comme le BorderImage CSS
(suite à la page suivante)

82
(suite de la page précédente)
frontière : 10, 10, 10, 10
source : '.. /examples/widgets/sequenced_images/data/images/
_white.png’
,!button
pos : self.pos
taille : auto.size

<RootWidget>
GridLayout :
_
size hint : . 9, . 9
_hint ' : . 5, 'center_y' : . 5}
pos : {'center_x
lignes : 1
Étiquette :
texte : "Je ne souffre pas de démence, je profite de chaque minute

_
text size : self.width-20, self.height-20
valign : 'top'
Étiquette :
texte : "Quand je suis né, j’ai été tellement surpris; Je n’ai pas parlé pendant
un an et demi.
_
text size : self.width-20, self.height-20
valign : 'middle'
halign : 'centre’
Étiquette :
texte : "Un consultant est quelqu’un qui prend un sujet que vous !
_
text size : self.width-20, self.height-20
valign : 'bottom'
halign : 'justifié’
'''')

classe RootWidget(FloatLayout) :
passer

class MainApp(App) :

def build(self) :
return RootWidget()
_ __ _ __
si _name == ' _main ':
MainApp(). run()

Le résultat devrait ressembler à ceci :

83
Comme nous contournons la règle de la classe GridLayout, toute utilisation de cette classe dans
notre application affichera cette image.
Que diriez-vous d’un fond animé?
Vous pouvez définir les instructions de dessin comme Rectangle/BorderImage/Ellipse/. . pour utiliser
une texture particulière :

Rectangle :
texture : référence à une texture

Nous l’utilisons pour afficher un arrière-plan animé :

à partir de l’application d’importation kivy.app


from kivy.uix.floatlayout import FloatLayout from
kivy.uix.gridlayout import GridLayout from
kivy.uix.image import Image
à partir de kivy.properties importer ObjectProperty à
partir de kivy.lang importer Builder

_
Builder.load string('''
<CustomLayout>
avant :
BorderImage :
# BorderImage se comporte comme la bordure CSS
BorderImage : 10, 10, 10, 10
(suite à la page suivante)

84
(suite de la page précédente)
image.texture
texture : self.background_
pos : self.pos
taille : auto.size

<RootWidget>
CustomLayout :
_
size hint : . 9, . 9
_hint ' : . 5, 'center_y' : . 5}
pos : {'center_x
lignes : 1
Étiquette :
texte : "Je ne souffre pas de démence, je profite de chaque minute

_
text size : self.width-20, self.height-20
valign : 'top'
Étiquette :
texte : "Quand je suis né, j’ai été tellement surpris; Je n’ai pas parlé pendant
un an et demi.
_
text size : self.width-20, self.height-20
valign : 'middle'
halign : 'centre’
Étiquette :
texte : "Un consultant est quelqu’un qui prend un sujet que vous !
_
text size : self.width-20, self.height-20
valign : 'bottom'
halign : 'justifié’
'''')

Classe CustomLayout (GridLayout) :


_
background image = ObjectProperty(
Image(
_animated.zip',
source='.. /examples/widgets/sequenced_images/data/images/ ,!button_white

_
anim delay=.1))

classe RootWidget(FloatLayout) :
passer

class MainApp(App) :

def build(self) :
return RootWidget()
_ __ _ __
si _name == ' _main ':
MainApp(). run()

Pour essayer de comprendre ce qui se passe ici, commencez à la ligne 13 :

85
_
texture : self.background image.texture
Ceci spécifie que la propriété texture de BorderImage sera mise à jour chaque fois que la propriété
texture de background_image est mise à jour. Nous définissons la propriété background_image à la
ligne 40 :

_
background image = ObjectProperty(...
Cela configure background_image comme une ObjectProperty dans laquelle nous ajoutons un widget
Image. Un widget d’image a une propriété de texture; où vous voyez self.background_image.texture, ceci
définit une référence, texture, à cette propriété. Le widget Image prend en charge l’animation : la texture
de l’image est mise à jour chaque fois que l’animation change, et la texture de l’instruction BorderImage est
mise à jour dans le processus.
Vous pouvez également simplement blit données personnalisées à la texture. Pour plus de détails,
consultez la documentation de Texture.

11.7 Dispositions d’imbrication

Oui! C’est assez amusant de voir à quel point le processus peut être extensible.

11.8 Mesures de la taille et de la position

L’unité par défaut de Kivy pour la longueur est le pixel, toutes les tailles et positions y sont exprimées
par défaut. Vous pouvez les exprimer dans d’autres unités, ce qui est utile pour obtenir une meilleure
cohérence entre les appareils (ils sont convertis en taille en pixels automatiquement).
Les unités disponibles sont pt, mm, cm, inch, dp et sp. Vous pouvez en apprendre davantage sur
leur utilisation dans la documentation des métriques.
Vous pouvez également expérimenter l’utilisation de l’écran pour simuler différents écrans
d’appareils pour votre application.

11.9 Séparation d’écran avec le gestionnaire d’écran

Si votre application est composée de divers écrans, vous voulez probablement un moyen facile de
naviguer d’un écran à l’autre. Heureusement, il y a la classe ScreenManager, qui vous permet de
définir des écrans séparément, et de définir la base de TransitionBase de l’un à l’autre.
86
CHAPITRE

DOUZE

GRAPHIQUES

12.1 Introduction à la toile

Une représentation graphique Widgets est rendue à l’aide d’une toile, que vous pouvez voir à la fois
comme un tableau à dessin illimité ou comme un ensemble d’instructions de dessin. Il y a de
nombreuses instructions que vous pouvez appliquer (ajouter) à votre toile, mais il y a deux variations
principales :
• instructions contextuelles
• instructions sur le vertex
Les instructions contextuelles ne dessinent rien, mais elles modifient les résultats des instructions du
vertex.
Les sollicitations peuvent contenir deux sous-ensembles d’instructions. Ils sont la toile.avant et la
toile. après les groupes d’instruction. Les instructions de ces groupes seront exécutées
respectivement avant et après le groupe canvas. Cela signifie qu’ils apparaîtront sous (être exécutés
avant) et au-dessus (être exécutés après). Ces groupes ne sont pas créés tant que l’utilisateur n’y
accède pas.
Pour ajouter une instruction canvas à un widget, vous utilisez le contexte canvas :

classe MyWidget(Widget) :
__ __
def init (self, **kwargs):
_ __
(*kwargs)
super(MyWidget, self). _init
avec self.canvas :
# ajouter vos instructions pour la toile principale ici

avec self.canvas.avant :
# vous pouvez l’utiliser pour ajouter des instructions rendues avant

avec self.canvas.after :
# vous pouvez l’utiliser pour ajouter des instructions rendues après

12.2 Instructions de contexte

Les instructions de contexte manipulent le contexte opengl. Vous pouvez faire pivoter, traduire et
mettre à l’échelle votre toile. Vous pouvez également fixer une texture ou changer la couleur du
dessin. Celui-ci est le plus couramment utilisé, mais d’autres sont vraiment utiles aussi :

avec self.canvas.avant :
Couleur(1, 0, .4, mode='rgb')
87
12.3 Instructions de dessin

Les instructions de dessin vont de très simples, comme tracer une ligne ou un polygone, à plus
complexes, comme des maillages ou des courbes béziers :

avec self.canvas :
# tracer une ligne en utilisant la couleur par
défaut Line(points=(x1, y1, x2, y2, x3, y3))

# permet de dessiner un carré rouge semi-


transparent Couleur(1, 0, 0, .5, mode='rgba')
Rectangle(pos=self.pos, size=self.size)

12.4 Instructions de manipulation

Parfois, vous voulez mettre à jour ou supprimer les instructions que vous avez ajoutées à une toile.
Cela peut se faire de différentes façons selon vos besoins :
Vous pouvez conserver une référence à vos instructions et les mettre à jour :

classe MyWidget(Widget) :
__ __
def init (self, **kwargs):
_ __
(*kwargs)
super(MyWidget, self). _init
avec self.canvas :
self.rect = Rectangle(pos=self.pos, size=self.size)
)
self.bind(pos=self.update_rect
)
self.bind(size=self.update_rect
_
def update rect(self, *args) :
self.rect.pos = self.pos
self.rect.size = self.size

Ou vous pouvez nettoyer votre toile et recommencer à zéro :

classe MyWidget(Widget) :
__ __
def init (self, **kwargs):
_ __
super(MyWidget, self). _init (*kwargs)
_my
self.draw _stuff()
)
self.bind(pos=self.draw_my_stuff
)
self.bind(size=self.draw_my_stuff
_stuff *
def draw_my (self, args) :
self.canvas.clear()

avec self.canvas :
self.rect = Rectangle(pos=self.pos, size=self.size)

Veuillez noter que la mise à jour des instructions est considérée comme la meilleure pratique, car elle
implique moins de frais généraux et évite de créer de nouvelles instructions.

88
CHAPITRE

TREIZE

LANGUE KV

13.1 Concept derrière le langage

À mesure que votre application devient plus complexe, il est fréquent que la construction d’arbres de
widget et la déclaration explicite des liaisons deviennent verbeuses et difficiles à maintenir. La langue
KV est une tentative pour surmonter ces lacunes.
Le langage KV, parfois appelé kvlang ou le langage kivy, vous permet de créer votre arborescence de
manière déclarative et de lier les propriétés des widget les unes aux autres ou aux callbacks de
manière naturelle. It allows for very fast prototypes and agile changes to your UI. It also facilitates
separating the logic of your application and its User Interface.

13.2 How to load KV

There are two ways to load Kv code into your application:


• By name convention:
Kivy looks for a Kv file with the same name as your App class in lowercase, minus “App” if it
ends with ‘App’ e.g:

MyApp -> my.kv

If this file defines a Root Widget it will be attached to the App’s root attribute and used as the
base of the application widget tree.
• Builder: You can tell Kivy to directly load a string or a file. If this string or file defines a root
widget, it will be returned by the method:

_
Builder.load file('path/to/file.kv') or:

_ _
Builder.load string(kv string)

89
13.3 Rule context

A Kv source constitutes of rules which are used to describe the content of a Widget. You can have
one root rule, and any number of class or template rules.
The root rule is declared by declaring the class of your root widget, without any indentation, followed
by : and will be set as the root attribute of the App instance:

Widget:

A class rule, declared by the name of a widget class between < > and followed by :, defines the
appearance and behavior of any instance of that class:

<MyWidget>:

Rules use indentation for delimitation, like Python. Indentation should be four spaces per level, like
the Python style guide recommends.
There are three keywords specific to the Kv language:
• app: always refers to the instance of your application.
• root: refers to the base widget/template in the current rule
• self : always refer to the current widget

13.4 Special syntax

There is a special syntax to define values for the whole Kv context.


To access Python modules and classes from kv, use #:import

#:import name x.y.z


#:import isdir os.path.isdir
#:import np numpy

is equivalent to:

from x.y import z as name


from os.path import isdir
import numpy as np

in Python.
To set a global value, use #:set

#:set name value

is equivalent to:

name = value

in Python.

90
13.5 Instantiate children

To declare a widget instance of some class as a child widget, just declare that child inside the rule:

MyRootWidget:
BoxLayout:
Button:
Button:

The example above defines that our root widget, an instance of MyRootWidget, has a child that is an
instance of the BoxLayout, and that BoxLayout further has two children, instances of the Button
class.
The Python equivalent of this code might be:

root = MyRootWidget()
box = BoxLayout()
_
box.add widget(Button())
_
box.add widget(Button())
_
root.add widget(box)

Which you may find less nice, both to read and to write.
Of course, in Python, you can pass keyword arguments to your widgets at creation to specify their
behaviour. For example, to set the number of columns of a gridlayout, we would do:

grid = GridLayout(cols=3)

To do the same thing in kv, you can set properties of the child widget directly in the rule:

GridLayout:
cols: 3

The value is evaluated as a Python expression, and all the properties used in the expression will be
observed, that means that if you had something like this in Python (this assume self is a widget with a
data ListProperty):

grid = GridLayout(cols=len(self.data))
self.bind(data=grid.setter('cols'))

To have your display updated when your data change, you can now have just:

GridLayout:
cols: len(root.data)

Note: Widget names should start with upper case letters while property names should start with lower
case ones. Following the PEP8 Naming Conventions is encouraged.

91
13.6 Event Bindings

You can bind to events in Kv using the “:” syntax, that is, associating a callback to an event:

Widget:
_ _
on size: my callback()
You can pass the values dispatched by the signal using the args keyword:

TextInput:
_
on text: app.search(args[1])
More complex expressions can be used, like:
_ _ _
pos: self.center x - self.texture size[0] / 2., self.center y - self.
size
,! texture_ [1] / 2.
_ _ _
This expression listens for a change in center x, center y, and texture size. If one of them
changes, the expression will be re-evaluated to update the pos field.
_
You can also handle on events inside your kv language. For example the TextInput class has a focus
_
property whose auto-generated on focus event can be accessed inside the kv language like so:
TextInput:
_
on focus: print(args)

13.7 Extend canvas

Kv lang can be used to define the canvas instructions of your widget like this:

MyWidget:
canvas:
Color:
rgba: 1, .3, .8, .5
Line:
points: zip(self.data.x, self.data.y)

And they get updated when properties values change.


Of course you can use canvas.before and canvas.after.

13.8 Referencing Widgets

In a widget tree there is often a need to access/reference other widgets. The Kv Language provides a
way to do this using id’s. Think of them as class level variables that can only be used in the Kv
language. Consider the following:

<MyFirstWidget>:
Button:
_
id: f but
TextInput:
_
text: f but.state
(continues on next page)

92
(continued from previous page)
<MySecondWidget>:
Button:
_
id: s but
TextInput:
_
text: s but.state
_
An id is limited in scope to the rule it is declared in, so in the code above s but can not be accessed
outside the <MySecondWidget> rule.

Warning: When assigning a value to id, remember that the value isn’t a string. There are no quotes:
good -> id: value, bad -> id: 'valeur’

An id is a weakref to the widget and not the widget itself. As a consequence, storing the id is not
sufficient to keep the widget from being garbage collected. To demonstrate:

<MyWidget>:
_ _
label widget: label widget
Button:
text: 'Add Button'
_ _ _
on press: root.add widget(label widget)
Button:
text: 'Remove Button'
_ _ _
on press: root.remove widget(label widget)
Label:
_
id: label widget
text: 'widget'

_
Although a reference to label widget is stored in MyWidget, it is not sufficient to keep the object
alive once other references have been removed because it’s only a weakref. Therefore, after the
remove button is clicked (which removes any direct reference to the widget) and the window is
_
resized (which calls the garbage collector resulting in the deletion of label widget), when the add
button is clicked to add the widget back, a ReferenceError: weakly-referenced object no longer
exists will be thrown.
_
To keep the widget alive, a direct reference to the label widget widget must be kept. This is achieved
__ __ _ __ __
using id. self or label widget. self in this case. The correct way to do this would be:
<MyWidget>:
_ _ __ __
label widget: label widget. self

13.9 Accessing Widgets defined inside Kv lang in your Python code

Consider the code below in my.kv:

<MyFirstWidget>:
# both these variables can be the same name and this doesn't lead to
# an issue with uniqueness as the id is only accessible in kv.
_ _
txt inpt: txt inpt
Button:
_
id: f but
TextInput:
(continues on next page)

93
(continued from previous page)
_
id: txt inpt
_
text: f but.state
_ _ _
on text: root.check status(f but)
In myapp.py:

...
class MyFirstWidget(BoxLayout):

_
txt inpt = ObjectProperty(None)
_
def check status(self, btn):
print('button state is: {state}'.format(state=btn.state))
_
print('text input text is: {txt}'.format(txt=self.txt inpt))
...

txt_inpt is defined as a ObjectProperty initialized to None inside the Class.

_
txt inpt = ObjectProperty(None)
At this point self.txt_inpt is None. In Kv lang this property is updated to hold the instance of the
TextInput referenced by the id txt_inpt.:

_ _
txt inpt: txt inpt
From this point onwards, self.txt_inpt holds a reference to the widget identified by the id txt_input and
can be used anywhere in the class, as in the function check_status. In contrast to this method you
could also just pass the id to the function that needs to use it, like in case of f_but in the code above.
There is a simpler way to access objects with id tags in Kv using the ids lookup object. You can do
this as follows:

<Marvel>
Label:
id: loki
text: 'loki: I AM YOUR GOD!'
Button:
id: hulk
text: "press to smash loki"
_ _
on release: root.hulk smash()
In your Python code:

class Marvel(BoxLayout):
_
def hulk smash(self):
self.ids.hulk.text = "hulk: puny god!"
_
self.ids["loki"].text = "loki: > <!!!" # alternative syntax
When your kv file is parsed, kivy collects all the widgets tagged with id’s and places them in this
self.ids dictionary type property. That means you can also iterate over these widgets and access them
dictionary style:

for key, val in self.ids.items():


print("key={0}, val={1}".format(key, val))

94
Note: Although the self.ids method is very concise, it is generally regarded as ‘best practice’ to use
the ObjectProperty. This creates a direct reference, provides faster access and is more explicit.

13.10 Dynamic Classes

Consider the code below:

<MyWidget>:
Button:
text: "Hello world, watch this text wrap inside the button"
_
text size: self.size
_
font size: '25sp'
markup: True
Button:
text: "Even absolute is relative to itself"
_
text size: self.size
_
font size: '25sp'
markup: True
Button:
text: "Repeating the same thing over and over in a comp = fail"
_
text size: self.size
_
font size: '25sp'
markup: True
Button:

Instead of having to repeat the same values for every button, we can just use a template instead, like so:

<MyBigButton@Button> :
_
text size: self.size
_
font size: '25sp'
markup: True

<MyWidget>:
MyBigButton:
text: "Hello world, watch this text wrap inside the button"
MyBigButton:
text: "Even absolute is relative to itself"
MyBigButton:
text: "repeating the same thing over and over in a comp = fail"
MyBigButton:

This class, created just by the declaration of this rule, inherits from the Button class and allows us to
change default values and create bindings for all its instances without adding any new code on the
Python side.

95
13.11 Re-using styles in multiple widgets

Consider the code below in my.kv:

<MyFirstWidget>:
Button:
_ _
on press: root.text(txt inpt.text)
TextInput:
_
id: txt inpt
<MySecondWidget>:
Button:
_ _
on press: root.text(txt inpt.text)
TextInput:
_
id: txt inpt
In myapp.py:

class MyFirstWidget(BoxLayout):

def text(self, val):


print('text input text is: {txt}'.format(txt=val))

class MySecondWidget(BoxLayout):

writing = StringProperty('')

def text(self, val):


self.writing = val

Because both classes share the same .kv style, this design can be simplified if we reuse that style for
both widgets. You can do this in .kv as follows. In my.kv:

<MyFirstWidget,MySecondWidget>:
Button:
_ _
on press: root.text(txt inpt.text)
TextInput:
_
id: txt inpt
By separating the class names with a comma, all the classes listed in the declaration will have the
same kv properties.

96
13.12 Designing with the Kivy Language

One of the aims of the Kivy language is to separate the concerns of presentation and logic. The
presentation (layout) side is addressed by your kv file and the logic by your .py file.

13.12.1 The code goes in py files

Let’s start with a little example: a Python file named main.py:

import kivy
kivy.require('1.0.5')

from kivy.uix.floatlayout import FloatLayout from


kivy.app import App
from kivy.properties import ObjectProperty, StringProperty

class Controller(FloatLayout):
'''Create a controller that receives a custom widget from the kv lang ,! file.

Add an action to be called from the kv lang file.


''''
_
label wid = ObjectProperty()
info = StringProperty()
_
def do action(self):
_
self.label wid.text = 'My label after button press' self.info = 'New
info text'

class ControllerApp(App):

def build(self):
return Controller(info='Hello world')

__ __ __ __
if name == ' main ':
ControllerApp(). run()

In this example, we are creating a Controller class with 2 properties:


• info for receiving some text
_
• label wid for receiving the label widget
_
In addition, we are creating a do action() method that will use both of these properties. It will change
_
the info text and change text in the label wid widget.

97
13.12.2 The layout goes in controller.kv

Executing this application without a corresponding .kv file will work, but nothing will be shown on the
screen. This is expected, because the Controller class has no widgets in it, it’s just a FloatLayout.
We can create the UI around the Controller class in a file named controller.kv, which will be loaded
when we run the ControllerApp. How this is done and what files are loaded is described in the
_
kivy.app.App.load kv() method.
1
#:kivy 1.0
2

3
<Controller> :
4
_ _ _
5
label wid: my custom label
6
BoxLayout:
7
orientation: 'vertical'
8
padding: 20
9

10
Button:
11
text: 'My controller info is: ' + root.info
12 _ _
on press: root.do action()
13

14
Label:
15
_ _
id: my custom label
16
text: 'My label before button press'

One label and one button in a vertical BoxLayout. Seems very simple. There are 3 things going on
here:
1. Using data from the Controller. As soon as the info property is changed in the controller, the
expression text: 'My controller info is: ' + root.info will automatically be re-evaluated,
changing the text in the Button.
_ _
2. Giving data to the Controller. The expression id: my custom label is assigning the created
_ _ _ _
Label the id of my custom label. Then, using my custom label in the expression
_ _ _
label wid: my custom label gives the instance of that Label widget to your Controller.
_
3. Creating a custom callback in the Button using the Controller’s on press method.
• root and self are reserved keywords, usable anywhere. root represents the top
widget in the rule and self represents the current widget.
• You can use any id declared in the rule the same as root and self. For example,
_
you could do this in the on press():
Button:
_ _ _ _ _
on press: root.do action(); my custom label.font size = 18
And that’s that. Now when we run main.py, controller.kv will be loaded so that the Button and Label
will show up and respond to our touch events.

98
13.13 More documentation

For a full description of the different components of the KV language, advanced usage and
limitations, see the documentation for lang

99
100
CHAPTER

FOURTEEN

INTEGRATING WITH OTHER


FRAMEWORKS

New in version 1.0.8.

14.1 Using Twisted inside Kivy

Note: You can use the kivy.support.install_twisted_reactor function to install a twisted reactor that will
run inside the kivy event loop.
Any arguments or keyword arguments passed to this function will be passed on the threadedse-lect
reactors interleave function. These are the arguments one would usually pass to twisted’s reac-
tor.startRunning

Warning: Unlike the default twisted reactor, the installed reactor will not handle any signals unless
you set the ‘installSignalHandlers’ keyword argument to 1 explicitly. This is done to allow kivy to
handle the signals as usual, unless you specifically want the twisted reactor to handle the signals
(e.g. SIGINT).

The kivy examples include a small example of a twisted server and client. The server app has a
simple twisted server running and logs any messages. The client app can send messages to the
server and will print its message and the response it got. The examples are based mostly on the
simple Echo example from the twisted docs, which you can find here:
• http://twistedmatrix.com/documents/current/_downloads/simpleserv.py
• http://twistedmatrix.com/documents/current/_downloads/simpleclient.py
To try the example, run echo_server_app.py first, and then launch echo_client_app.py. The server will
reply with simple echo messages to anything the client app sends when you hit enter after typing
something in the textbox.

101
14.1.1 Server App

_ _
# install twisted rector must be called before importing and using the ,! reactor
_ _
from kivy.support import install twisted reactor
_ _
install twisted reactor()
from twisted.internet import reactor
from twisted.internet import protocol

class EchoServer(protocol.Protocol):
def dataReceived(self, data):
_
response = self.factory.app.handle message(data)
if response:
self.transport.write(response)

class EchoServerFactory(protocol.Factory):
protocol = EchoServer
__ __
def init (self, app):
self.app = app

from kivy.app import App


from kivy.uix.label import Label

class TwistedServerApp(App):
label = None

def build(self):
self.label = Label(text="server started\n")
reactor.listenTCP(8000, EchoServerFactory(self)) return
self.label
_
def handle message(self, msg):
msg = msg.decode('utf-8')
self.label.text = "received: {}\n".format(msg)

if msg == "ping":
msg = "Pong"
if msg == "plop":
msg = "Kivy Rocks!!!"
self.label.text += "responded: {}\n".format(msg)
return msg.encode('utf-8')

__ __ __ __
if name == ' main ':
TwistedServerApp(). run()

102
14.1.2 Client App

_ _
# install twisted rector must be called before importing the reactor from
__ __ _
future import unicode literals
_ _
from kivy.support import install twisted reactor
_ _
install twisted reactor()
# A Simple Client that send messages to the Echo Server from
twisted.internet import reactor, protocol

class EchoClient(protocol.Protocol):
def connectionMade(self):
_
self.factory.app.on connection(self.transport)
def dataReceived(self, data):
_
self.factory.app.print message(data.decode('utf-8'))

class EchoClientFactory(protocol.ClientFactory):
protocol = EchoClient
__ __
def init (self, app):
self.app = app

def startedConnecting(self, connector):


_
self.app.print message('Started to connect.')

def clientConnectionLost(self, connector, reason):


_
self.app.print message('Lost connection.')
def clientConnectionFailed(self, connector, reason):
_
self.app.print message('Connection failed.')

from kivy.app import App


from kivy.uix.label import Label
from kivy.uix.textinput import TextInput from
kivy.uix.boxlayout import BoxLayout

# A simple kivy App, with a textbox to enter messages, and


# a large label to display all the messages received from
# the server
class TwistedClientApp(App):
connection = None
textbox = None
label = None

def build(self):
_
root = self.setup gui()
_ _
self.connect to server()
(continues on next page)

103
(continued from previous page)
return root
_
def setup gui(self):
_ _
self.textbox = TextInput(size hint y=.1, multiline=False)
_ _ _
self.textbox.bind(on text validate=self.send message)
self.label = Label(text='connecting...\n')
layout = BoxLayout(orientation='vertical')
_
layout.add widget(self.label)
_
layout.add widget(self.textbox)
return layout
_ _
def connect to server(self):
reactor.connectTCP('localhost', 8000, EchoClientFactory(self))
_
def on connection(self, connection):
_
self.print message("Connected successfully!")
self.connection = connection
_
def send message(self, *args):
msg = self.textbox.text
if msg and self.connection:
self.connection.write(msg.encode('utf-8'))
self.textbox.text = ""
_
def print message(self, msg):
self.label.text += "{}\n".format(msg)

__ __ __ __
if name == ' main ':
TwistedClientApp(). run()

104
CHAPTER

FIFTEEN

PACKAGING YOUR APPLICATION

15.1 Create a package for Windows

Note: This document only applies for kivy 1.9.1 and greater.

Packaging your application for the Windows platform can only be done inside the Windows OS. The
following process has been tested on Windows with the Kivy wheels installation, see at the end for
alternate installations.
The package will be either 32 or 64 bits depending on which version of Python you ran it with.

15.1.1 Requirements

• Latest Kivy (installed as described in installation_windows).


• PyInstaller 3.1+ (pip install --upgrade pyinstaller).

15.2 PyInstaller default hook

This section applies to PyInstaller (>= 3.1) that includes the kivy hooks. To overwrite the default hook
the following examples need to be slightly modified. See Overwriting the default hook.

15.2.1 Packaging a simple app

For this example, we’ll package the touchtracer example project and embed a custom icon. The
location of the kivy examples is, when using the wheels, installed to python\\share\\kivy-examples
and when using the github source code installed as kivy\\examples. We’ll just refer to the full path
leading to the examples as examples-path. The touchtracer example is in examples-path\\demo\
\touchtracer and the main file is named main.py.
1. Open your command line shell and ensure that python is on the path (i.e. python works).
2. Create a folder into which the packaged app will be created. For example create a TouchApp
folder and change to that directory with e.g. cd TouchApp. Then type:

python -m PyInstaller --name touchtracer examples-path\demo\


,!touchtracer\main.py

105
You can also add an icon.ico file to the application folder in order to create an icon for the
executable. If you don’t have a .ico file available, you can convert your icon.png file to ico using
the web app ConvertICO. Save the icon.ico in the touchtracer directory and type:

python -m PyInstaller --name touchtracer --icon examples-path\demo\


,!touchtracer\icon.ico examples-path\demo\touchtracer\main.py

For more options, please consult the PyInstaller Manual.


3. The spec file will be touchtracer.spec located in TouchApp. Now we need to edit the spec file
to add the dependencies hooks to correctly build the exe. Open the spec file with your favorite
editor and add these lines at the beginning of the spec (assuming sdl2 is used, the default now):
_
from kivy deps import sdl2, glew

Then, find COLLECT() and add the data for touchtracer (touchtracer.kv, particle.png, . . . ):
Change the line to add a Tree() object, e.g. Tree('examples-path\\demo\\touchtracer\\'). This
Tree will search and add every file found in the touchtracer directory to your final package.
To add the dependencies, before the first keyword argument in COLLECT add a Tree object for
_ _
every path of the dependencies. E.g. *[Tree(p) for p in (sdl2.dep bins + glew. dep bins)] so
it’ll look something like:
coll = COLLECT(exe, Tree('examples-path\\demo\\touchtracer\\'), a.binaries,

a.zipfiles,
a.datas,
_ _
*[Tree(p) for p in (sdl2.dep bins + glew.dep bins)], strip=False,
upx=True,
name='touchtracer')

4. Now we build the spec file in TouchApp with:

python -m PyInstaller touchtracer.spec

5. The compiled package will be in the TouchApp\dist\touchtracer directory.

15.2.2 Single File Application

Next, we will modify the example above to package the touchtracer example project as a single file
application. Following the same steps as above, instead issue the following command:

python -m PyInstaller --onefile --name touchtracer examples-path\demo\


,!touchtracer\main.py

1. As before, this will generate touchtracer.spec, which we will edit to add the dependencies. In
this instance, edit the arguments to the EXE command so that it will look something like this:

exe = EXE(pyz, Tree('examples-path\\demo\\touchtracer\\'), a.scripts,

a.binaries,
a.zipfiles,
a.datas,
_ _
*[Tree(p) for p in (sdl2.dep bins + glew.dep bins)], upx=True
name='touchtracer')

106
2. Now you can build the spec file as before with:

python -m PyInstaller touchtracer.spec

3. The compiled package will be in the TouchApp\dist directory and will consist of a single
executable file.

15.2.3 Bundling Data Files

We will again modify the previous example to include bundled data files. PyInstaller allows inclusion
of outside data files (such as images, databases, etc) that the project needs to run. When running an
app on Windows, the executable extracts to a temporary folder which the Kivy project doesn’t know
about, so it can’t locate these data files. We can fix that with a few lines.
1. First, follow PyInstaller documentation on how to include data files in your application.
2. Modify your main python code to include the following imports (if it doesn’t have them already):

import os, sys


_ _ _
from kivy.resources import resource add path, resource find
3. Modify your main python code to include the following (using the touchtracer app as an
example):
__ __ __ __
if name == ' main ':
_
if hasattr(sys, ' MEIPASS'):
_ _ _
resource add path(os.path.join(sys. MEIPASS))
TouchtracerApp(). run()

4. Finally, follow the steps for bundling your application above.

15.2.4 Packaging a video app with gstreamer

Following we’ll slightly modify the example above to package a app that uses gstreamer for video.
We’ll use the videoplayer example found at examples-path\widgets\videoplayer.py. Create a
folder somewhere called VideoPlayer and on the command line change your current directory to that
folder and do:

python -m PyInstaller --name gstvideo examples-path\widgets\videoplayer.py

to create the gstvideo.spec file. Edit as above and this time include the gstreamer dependency as
well:

_
from kivy deps import sdl2, glew, gstreamer
and add the Tree() to include the video files, e.g. Tree('examples-path\\widgets') as well as the
gstreamer dependencies so it should look something like:

coll = COLLECT(exe, Tree('examples-path\\widgets'), a.binaries,

a.zipfiles,
a.datas,
_ _ _
*[Tree(p) for p in (sdl2.dep bins + glew.dep bins + ,!gstreamer.dep bins)],
strip=False,
(continues on next page)

107
(continued from previous page)
upx=True,
name='gstvideo')

Then build the spec file in VideoPlayer with:

python -m PyInstaller gstvideo.spec

and you should find gstvideo.exe in VideoPlayer\dist\gstvideo, which when run will play a video.

Note: If you’re using Pygame and need PyGame in your packaging app, you’ll have to add the
following code to your spec file due to kivy issue #1638. After the imports add the following:

def getResource(identifier, *args, **kwargs):


_
if identifier == 'pygame icon.tiff':
raise IOError()
_ _
return original getResource(identifier, *args, **kwargs)
import pygame.pkgdata
_ _
original getResource = pygame.pkgdata.getResource
pygame.pkgdata.getResource = getResource

15.3 Overwriting the default hook

15.3.1 Including/excluding video and audio and reducing app size

PyInstaller includes a hook for kivy that by default adds all the core modules used by kivy, e.g. audio,
video, spelling etc (you still need to package the gstreamer dlls manually with Tree() - see the
example above) and their dependencies. If the hook is not installed or to reduce app size some of
these modules may be excluded, e.g. if no audio/video is used, with an alternative hook.
Kivy provides the alternate hook at hookspath(). In addition, if and only if PyInstaller doesn’t have the
_
default hooks runtime hooks() must also be provided. When overwriting the hook, the latter one
typically is not required to be overwritten.
The alternate hookspath() hook does not include any of the kivy providers. To add them, they have to be
_ _ _ _ _
added with get deps minimal() or get deps all(). See their documentation and pyinstaller hooks for
_ _
more details. But essentially, get deps all() add all the providers like in the default hook while
_ _
get deps minimal() only adds those that are loaded when the app is run. Each method provides a list of
hidden kivy imports and excluded imports that can be passed on to Analysis.
One can also generate a alternate hook which literally lists every kivy provider module and those not
_
required can be commented out. See pyinstaller hooks.
To use the the alternate hooks with the examples above modify as following to add the hooks with
_ _ _ _ _
hookspath() and runtime hooks (if required) and **get deps minimal() or **get deps all()
to specify the providers.
For example, add the import statement:
_ _ _ _ _
from kivy.tools.packaging.pyinstaller hooks import get deps minimal, get ,!deps all,
_
hookspath, runtime hooks

108
and then modify Analysis as follows:

a = Analysis(['examples-path demo touchtracer main.py'],


...
hookspath=hookspath(),
_ _
runtime hooks=runtime hooks(),
...
_ _
**get deps all())
to include everything like the default hook. Or:

a = Analysis(['examples-path demo touchtracer main.py'],


...
hookspath=hookspath(),
_ _
runtime hooks=runtime hooks(),
...
_ _
**get deps minimal(video=None, audio=None))
e.g. to exclude the audio and video providers and for the other core modules only use those loaded.
The key points is to provide the alternate hookspath() which does not list by default all the kivy
providers and instead manually to hiddenimports add the required providers while removing the
_ _
undesired ones (audio and video in this example) with get deps minimal().

15.3.2 Alternate installations


_ _
The previous examples used e.g. *[Tree(p) for p in (sdl2.dep bins + glew.dep bins +
_
gstreamer.dep bins)], to make PyInstaller add all the dlls used by these dependencies. If kivy was
_
not installed using the wheels method these commands will not work and e.g. kivy deps.sdl2 will fail
to import. Instead, one must find the location of these dlls and manually pass them to the Tree class
in a similar fashion as the example.

15.4 Create a package for Android

You can create a package for android using the python-for-android project. This page explains how to
download and use it directly on your own machine (see Packaging with python-for-android) or use the
Buildozer tool to automate the entire process. You can also see Packaging your application for the
Kivy Launcher to run kivy programs without compiling them.
For new users, we recommend using Buildozer as the easiest way to make a full APK. You can also
run your Kivy app without a compilation step with the Kivy Launcher app.
Kivy applications can be released on an Android market such as the Play store, with a few extra steps
to create a fully signed APK.
The Kivy project includes tools for accessing Android APIs to accomplish vibration, sensor access,
texting etc. These, along with information on debugging on the device, are documented at the main
Android page.

109
15.4.1 Buildozer

Buildozer is a tool that automates the entire build process. It downloads and sets up all the
prerequisites for python-for-android, including the android SDK and NDK, then builds an apk that can
be automatically pushed to the device.
Buildozer currently works only in Linux, and is a beta release, but it already works well and can
significantly simplify the apk build.
You can get buildozer at https://github.com/kivy/buildozer:

git clone https://github.com/kivy/buildozer.git cd buildozer

sudo python setup.py install

This will install buildozer in your system. Afterwards, navigate to your project directory and run:

buildozer init

This creates a buildozer.spec file controlling your build configuration. You should edit it appropriately
with your app name etc. You can set variables to control most or all of the parameters passed to
python-for-android.
Install buildozer’s dependencies.
Finally, plug in your android device and run:

buildozer android debug deploy run

to build, push and automatically run the apk on your device.


Buildozer has many available options and tools to help you, the steps above are just the simplest way
to build and run your APK. The full documentation is available here. You can also check the Buildozer
README at https://github.com/kivy/buildozer.

15.4.2 Packaging with python-for-android

You can also package directly with python-for-android, which can give you more control but requires
you to manually download parts of the Android toolchain.
See the python-for-android documentation for full details.

15.4.3 Packaging your application for the Kivy Launcher

The Kivy launcher is an Android application that runs any Kivy examples stored on your SD Card. To
install the Kivy launcher, you must:
1. Go to the Kivy Launcher page on the Google Play Store
2. Click on Install
3. Select your phone. . . And you’re done!
If you don’t have access to the Google Play Store on your phone/tablet, you can download and install
the APK manually from http://kivy.org/#download.
Once the Kivy launcher is installed, you can put your Kivy applications in the Kivy directory in your
external storage directory (often available at /sdcard even in devices where this memory is internal),
e.g.

110
/sdcard/kivy/<yourapplication>

<yourapplication> should be a directory containing:

# Your main application file:


main.py
# Some info Kivy requires about your app on android:
android.txt

The file android.txt must contain:

title=<Application Title>
author=<Your Name>
orientation=<portrait|landscape>

These options are just a very basic configuration. If you create your own APK using the tools above,
you can choose many other settings.

Installation of Examples

Kivy comes with many examples, and these can be a great place to start trying the Kivy launcher. You
can run them as below:

#. Download the `Kivy demos for Android <https://storage.googleapis.com/ ,! google-code-


_
archive-downloads/v2/code.google.com/kivy/kivydemo-for-,!android.zip>`
#. Unzip the contents and go to the folder `kivydemo-for-android`
#. Copy all the the subfolders here to

/sdcard/kivy
1. Run the launcher and select one of the Pictures, Showcase, Touchtracer, Cymunk or other de-
mos. . .

15.4.4 Release on the market

If you have built your own APK with Buildozer or with python-for-android, you can create a release
version that may be released on the Play store or other Android markets.
To do this, you must run Buildozer with the release parameter (e.g. buildozer android release), or if
using python-for-android use the --release option to build.py. This creates a release APK in the bin
directory, which you must properly sign and zipalign. The procedure for doing this is described in the
Android documentation at https://developer.android.com/studio/publish/ app-signing.html#signing-
manually - all the necessary tools come with the Android SDK.

111
15.4.5 Targeting Android

Kivy is designed to operate identically across platforms and as a result, makes some clear design
decisions. It includes its own set of widgets and by default, builds an APK with all the required core
dependencies and libraries.
It is possible to target specific Android features, both directly and in a (somewhat) cross-platform way.
See the Using Android APIs section of the Kivy on Android documentation for more details.

15.5 Kivy on Android

You can run Kivy applications on Android, on (more or less) any device with OpenGL ES 2.0 (Android
2.2 minimum). This is standard on modern devices; Google reports the requirement is met by 99.9%
of devices.
Kivy APKs are normal Android apps that you can distribute like any other, including on stores like the
Play store. They behave properly when paused or restarted, may utilise Android services and have
access to most of the normal java API as described below.
Follow the instructions below to learn how to package your app for Android, debug your code on the
device, and use Android APIs such as for vibration and reading sensors.

15.5.1 Package for Android

The Kivy project provides all the necessary tools to package your app on Android, including building
your own standalone APK that may be distributed on a market like the Play store. This is covered fully
in the Create a package for Android documentation.

15.5.2 Debugging your application on the Android platform

You can view the normal output of your code (stdout, stderr), as well as the normal Kivy logs, through the
Android logcat stream. This is accessed through adb, provided by the Android SDK. You may need to
enable adb in your device’s developer options, then connect your device to your computer and run:

adb logcat

You’ll see all the logs including your stdout/stderr and Kivy logger.
If you packaged your app with Buildozer, the adb tool may not be in your $PATH and the above
command may not work. You can instead run:

buildozer android logcat

to run the version installed by Buildozer, or find the SDK tools at $HOME/.buildozer/android/
platform.
You can also run and debug your application using the Kivy Launcher. If you run your application this
way, you will find log files inside the “/.kivy/logs” sub-folder within your application folder.

112
15.5.3 Using Android APIs

Although Kivy is a Python framework, the Kivy project maintains tools to easily use the normal java
APIs, for everything from vibration to sensors to sending messages through SMS or email.
For new users, we recommend using Plyer. For more advanced access or for APIs not currently
wrapped, you can use Pyjnius directly. Kivy also supplies an android module for basic Android func-
tionality.
User contributed Android code and examples are available on the Kivy wiki.

Plyer

Plyer is a pythonic, platform-independent API to use features commonly found on various platforms,
particularly mobile ones. The idea is that your app can call simply call a Plyer function, such as to
present a notification to the user, and Plyer will take care of doing so in the right way regardless of the
platform or operating system. Internally, Plyer uses Pyjnius (on Android), Pyobjus (on iOS) and some
platform specific APIs on desktop platforms.
For instance, the following code would make your Android device vibrate, or raise a NotImplemented-
Error that you can handle appropriately on other platforms such as desktops that don’t have
appropriate hardware::

from plyer import vibrator


vibrateur.vibrate(10) # vibrate for 10 seconds

Plyer’s list of supported APIs is growing quite quickly, you can see the full list in the Plyer README.

Pyjnius

Pyjnius is a Python module that lets you access java classes directly from Python, automatically
converting arguments to the right type, and letting you easily convert the java results to Python.
Pyjnius can be obtained from github, and has its own documentation.
Here is a simple example showing Pyjnius’ ability to access the normal Android vibration API, the
same result of the plyer code above:

# 'autoclass' takes a java class and gives it a Python wrapper from jnius
import autoclass

# Context is a normal java class in the Android API


Context = autoclass('android.content.Context')

# PythonActivity is provided by the Kivy bootstrap app in python-for-,!android

PythonActivity = autoclass('org.renpy.android.PythonActivity')

# The PythonActivity stores a reference to the currently running activity


# We need this to access the vibrator service
activity = PythonActivity.mActivity

# This is almost identical to the java code for the vibrator vibrator =
_
activity.getSystemService(Context.VIBRATOR SERVICE)
vibrateur.vibrate(10000) # The value is in milliseconds - this is 10s

113
This code directly follows the java API functions to call the vibrator, with Pyjnius automatically
translating the api to Python code and our calls back to the equivalent java. It is much more verbose
and java-like than Plyer’s version, for no benefit in this case, though Plyer does not wrap every API
available to Pyjnius.
Pyjnius also has powerful abilities to implement java interfaces, which is important for wrapping some
APIs, but these are not documented here - you can see Pyjnius’ own documentation.

Android module

Python-for-android includes a python module (actually cython wrapping java) to access a limited set
of Android APIs. This has been largely superseded by the more flexible Pyjnius and Plyer as above,
but may still occasionally be useful. The available functions are given in the python-for-android
documentation.
This includes code for billing/IAP and creating/accessing Android services, which is not yet available
in the other tools above.

15.5.4 Status of the Project and Tested Devices

These sections previously described the existence of Kivy’s Android build tools, with their limitations
and some devices that were known to work.
The Android tools are now quite stable, and should work with practically any device; our minimum
requirements are OpenGL ES 2.0 and Android 2.2. These are very common now - Kivy has even
been run on an Android smartwatch!
A current technical limitation is that the Android build tools compile only ARM APKs, which will not run
on Android devices with x86 processors (these are currently rare). This should be added soon.
As Kivy works fine on most devices, the list of supported phones/tablets has been retired - all Android
devices are likely to work if they meet the conditions above.

15.6 Creating packages for OS X

Note: This guide describes multiple ways for packaging Kivy applications. Packaging with PyInstaller
is recommended for general use.

15.6.1 Using the Kivy SDK

Note: These instructions apply only from Kivy v2.0.0 onwards.

Note: Kivy.app is built on the current GitHub Action macOS version (10.15) and will typically not work
on older OS X versions. For older OS X versions, you need to build Kivy.app on the oldest machine
you wish to support. See below.

For OS X 10.15+ and later, we provide a Kivy DMG with all dependencies bundled in a virtual
environment, including a Python interpreter that can be used as a base to package kivy apps.

114
This is the safest approach because it packages the binaries without references to any binaries on the
system on which the app is packaged. Because all references are to frameworks included in the dmg
or to binaries with the dmg. As opposed to e.g. pyinstaller which copies binaries from your local
python installation.
You can find complete instructions to build and package apps with Kivy.app, starting either with
Kivy.app or building from scratch, in the readme of the kivy-sdk-packager repo.

15.6.2 Using PyInstaller and Homebrew

Note: Package your app on the oldest OS X version you want to support.

Complete guide

1. Install Homebrew
2. Install Python:

$ brew install python

Note: To use Python 3, brew install python3 and replace pip with pip3 in the guide below.

3. (Re)install your dependencies with --build-from-source to make sure they can be used on
other machines:

_ _ _
$ brew reinstall --build-from-source sdl2 sdl2 image sdl2 ttf sdl2 ,!mixer

Note: If your project depends on GStreamer or other additional libraries (re)install them with --
build-from-source as described below.

4. Install Cython and Kivy:


_
$ pip install |cython install|
$ pip install -U kivy

5. Install PyInstaller:

$ pip install -U pyinstaller

6. Package your app using the path to your main.py:


$ pyinstaller -y --clean --windowed --name touchtracer \ --exclude-
_
module tkinter \
--exclude-module Tkinter \ --exclude-module enchant \ --exclude-
module twisted \ /usr/local/share/kivy-
examples/demo/touchtracer/main.py

115
Note: This will not yet copy additional image or sound files. You would need to adapt the
created .spec file for that.

Editing the spec file

The specs file is named touchtracer.spec and is located in the directory where you ran the pyinstaller
command.
You need to change the COLLECT() call to add the data of touchtracer (touchtracer.kv, particle.png, . . . ).
Change the line to add a Tree() object. This Tree will search and add every file found in the touchtracer
directory to your final package. Your COLLECT section should look something like this:

coll = COLLECT(exe, Tree('/usr/local/share/kivy-examples/demo/touchtracer/ ,!'),

a. binaires,
a.zipfiles,
a.datas,
strip=None,
upx=True,
name='touchtracer')

This will add the required hooks so that PyInstaller gets the required Kivy files. We are done. Your
spec is ready to be executed.

Build the spec and create a DMG

1. Open a console.
2. Go to the PyInstaller directory, and build the spec:

$ pyinstaller -y --clean --windowed touchtracer.spec

3. Run:

$ pushd dist
$ hdiutil create ./Touchtracer.dmg -srcfolder touchtracer.app -ov $ popd

4. You will now have a Touchtracer.dmg available in the dist directory.

Additional Libraries

GStreamer

If your project depends on GStreamer:

$ brew reinstall --build-from-source gstreamer gst-plugins-{base,good,bad, ,!ugly}

Note: If your Project needs Ogg Vorbis support be sure to add the --with-libvorbis option to the
command above.

116
Traduit de Anglais vers Français - www.onlinedoctranslator.com

Partie IV

RÉFÉRENCE API

La référence API est une liste lexicographique de toutes les différentes classes, méthodes et fonctionnalités proposées par Kivy.

155
156
CHAPITRE

VINGT

CADRE KIVY

Kivy est une bibliothèque open source pour le développement d'applications multi-touch.
C'est multiplateforme
(Linux/OSX/Windows/Android/iOS) et publié sous les termes de laLicence MIT.

Il est livré avec une prise en charge native de nombreux périphériques d'entrée multi-touch, une bibliothèque croissante de widgets
multi-touch et un dessin OpenGL accéléré par le matériel. Kivy est conçu pour vous permettre de vous concentrer sur la création
d'applications personnalisées et hautement interactives aussi rapidement et facilement que possible.

Avec Kivy, vous pouvez profiter pleinement de la nature dynamique de Python. Il existe des milliers de bibliothèques gratuites de haute
qualité qui peuvent être intégrées dans votre application. Dans le même temps, les pièces critiques en termes de performances sont
mises en œuvre à l'aide deCython.

Voir http://kivy.org pour plus d'informations.

kivy.kivy_base_dir = '/home/docs/checkouts/readthedocs.org/user_builds/kivy/envs/latest/
lib/python3.7/site-packages/kivy'
Annuaire Kivy
kivy.kivy_config_fn = ''
Nom du fichier de configuration Kivy

kivy.kivy_configure()
Appelez la post-configuration de Kivy. Cette fonction doit être appelée si vous créez vous-même la fenêtre.

kivy.kivy_data_dir = '/home/docs/checkouts/readthedocs.org/user_builds/kivy/envs/latest/
lib/python3.7/site-packages/kivy/data'
Annuaire de données Kivy

kivy.kivy_examples_dir = '/home/docs/checkouts/readthedocs.org/user_builds/kivy/envs/latest/
share/kivy-examples'
Répertoire d'exemples Kivy

kivy.kivy_home_dir = ''
Répertoire de stockage utilisateur Kivy

kivy.kivy_icons_dir = '/home/docs/checkouts/readthedocs.org/user_builds/kivy/envs/latest/
lib/python3.7/site-packages/kivy/data/icons/'
Chemin de configuration des icônes Kivy (ne supprimez pas le dernier '')

kivy.kivy_options = {'audio': 'sdl2', ('gstplayer', 'pygame', 'ffpyplayer', ('opencv', 'gi',


'avplayer'), 'caméra' : 'avfoundation', 'android',
'picamera'), 'clipboard' : ('android', 'winctypes', 'xsel', 'xclip', 'dbusklipper', 'nspaste', 'sdl2',
'pygame', 'dummy', 'gtk3') , 'image': ('tex', 'imageio', 'dds', 'sdl2', 'pygame', 'pil', 'ffpy', 'gif'),
'spelling': ('enchant', 'osxappkit '), 'text' : ('pil', 'sdl2', 'pygame', 'sdlttf'), 'video' : ('gstplayer',
'ffmpeg', 'ffpyplayer', 'null'), 'window' : ('egl_rpi', 'sdl2', 'pygame', 'sdl', 'x11')}

Options de paramètres globaux pour kivy

157
kivy.kivy_register_post_configuration(rappeler)
Enregistrez une fonction à appeler lorsque kivy_configure() est appelé.

Avertissement: Usage interne uniquement.

kivy.kivy_shader_dir = '/home/docs/checkouts/readthedocs.org/user_builds/kivy/envs/latest/
lib/python3.7/site-packages/kivy/data/glsl'
Répertoire des shaders Kivy glsl

kivy.kivy_usermodules_dir = ''
Répertoire des modules utilisateur Kivy

kivy.parse_kivy_version(version)
Analyse la version kivy comme décrit dans exiger() dans un 3-uplet de ([x, y, z], 'rc|a|b|dev|post', 'N') où N est la
révision de la balise. Les deux derniers éléments peuvent être Aucun.

kivy.exiger(version)
Require peut être utilisé pour vérifier la version minimale requise pour exécuter une application Kivy. Par exemple, vous
pouvez démarrer votre code d'application comme ceci :

importer kivy
kivy.exiger('1.0.1')

Si un utilisateur tente d'exécuter votre application avec une version de Kivy antérieure à la version spécifiée, une
exception est déclenchée.

La chaîne de version Kivy est construite comme ceci :

X.Oui.Z[étiqueter[révision de balise]]

X est la version majeure Y est la


version mineure Z est la révision
des corrections de bugs

La balise est facultative, mais peut être l'une des suivantes : '.dev', '.post', 'a', 'b' ou 'rc'. Le tagrevision est le numéro de
révision du tag.

Avertissement: Vous ne devez pas demander une version avec une balise, sauf -dev. Demander une version 'dev'
avertira simplement l'utilisateur si la version actuelle de Kivy n'est pas une -dev, mais cela ne lèvera jamais
d'exception. Vous ne devez pas demander une version avec une baliserévision.

20.1 PAS DE DOCUMENTATION (module kivy.uix.recycleview)

20.2 Animation

Animation et AnimationTransition sont utilisés pour animer Widget Propriétés. Vous devez spécifier au moins un nom
de propriété et une valeur cible. Pour utiliser une animation, procédez comme suit :

• Configurer un objet Animation

• Utiliser l'objet Animation sur un Widget

158
20.2.1 Animations simples

Pour animer la position x ou y d'un widget, spécifiez simplement les valeurs x/y cibles où vous souhaitez que le widget
soit positionné à la fin de l'animation :

anime = Animation(X=100, oui=100)


anime.début(widget)

L'animation durera 1 seconde à moins que durée est spécifié. Lorsque anim.start() est appelé, le Widget se
déplacera en douceur de la position x/y actuelle à (100, 100).

20.2.2 Propriétés et transitions multiples

Vous pouvez animer plusieurs propriétés et utiliser des fonctions de transition intégrées ou personnalisées à l'aide de transition
(ou la t= raccourci). Par exemple, pour animer la position et la taille à l'aide de la transition 'in_quad' :

anime = Animation(X=50, Taille=(80, 80), t='in_quad') anime.début(


widget)

Notez que le t= le paramètre peut être le nom de chaîne d'une méthode dans le AnimationTransition classe ou votre
propre fonction d'animation.

20.2.3 Animation séquentielle

Pour joindre les animations de manière séquentielle, utilisez l'opérateur '+'. L'exemple suivant s'animera à x=50 sur 1 seconde,
puis animera la taille à (80, 80) au cours des deux prochaines secondes :

anime = Animation(X=50) + Animation(Taille=(80, 80), durée=2.) anime.début(


widget)

20.2.4 Animation parallèle

Pour joindre des animations en parallèle, utilisez l'opérateur '&'. L'exemple suivant animera la position à
(80, 10) sur 1 seconde, tout en animant en parallèle la taille à (800, 800) :

anime = Animation(position=(80, dix))


anime &= Animation(Taille=(800, 800), durée=2.) anime.début(
widget)

Gardez à l'esprit que la création d'animations qui se chevauchent sur la même propriété peut avoir des résultats
inattendus. Si vous souhaitez appliquer plusieurs animations à la même propriété, vous devez soit les planifier de
manière séquentielle (via l'opérateur '+' ou en utilisant leon_complete rappel) ou annuler les animations précédentes en
utilisant le Tout annuler méthode.

159
20.2.5 Répétition d'animation

Nouveau dans la version 1.8.0.

Noter: Ceci n'est actuellement implémenté que pour les animations 'Sequence'.

Pour définir une animation à répéter, définissez simplement le Séquence.répéter propriété à Vrai:

anime = Animation(...) + Animation(...) anime.


répéter = Vrai anime.début(widget)

Pour le contrôle de flux d'animations telles que l'arrêt et l'annulation, utilisez les méthodes déjà en place dans le module
d'animation.

classer kivy.animation.Animation(**kw)
Bases : kivy.event.EventDispatcher
Créez une définition d'animation qui peut être utilisée pour animer un widget.

Paramètres

durée ou ré: flottant, la valeur par défaut est 1. Durée de l'animation, en secondes.

transition ou t: str ou func Fonction de transition pour les propriétés animées. Cela peut être le
nom d'une méthode de AnimationTransition.
étape ou s: flotter Étape en millisecondes de l'animation. La valeur par défaut est 0, ce qui signifie
l'animation est mise à jour pour chaque image.

Pour mettre à jour l'animation moins souvent, définissez la valeur du pas sur un flottant. Par exemple, si
vous souhaitez animer à 30 FPS, utilisez s=1/30.

Événements

on_start: animation, widget Lancé lorsque l'animation est lancée sur un widget.

on_complete: animation, widget Lancé lorsque l'animation est terminée ou


arrêté sur un widget.

on_progress: animation, widget, progression Tiré lorsque la progression de la


l'animation change.
Modifié dans la version 1.4.0 : Ajout du paramètre s/step.

Modifié dans la version 1.10.0 : la valeur par défaut du paramètre step a été modifiée de 1/60. à 0.

propriété animée_propriétés
Renvoie les propriétés utilisées pour l'animation.

Annuler(widget)
Annuler l'animation précédemment appliquée à un widget. Même effet quearrêter, à l'exception du on_complete
l'événement sera ne pas être déclenché !

Nouveau dans la version 1.4.0.

statique cancel_all(widget, *grands)


Annulez toutes les animations qui concernent un widget/une liste de propriétés spécifique. VoirAnnuler.

Exemple:

anime = Animation(X=50)
anime.début(widget)
(suite à la page suivante)

160
(suite de la page précédente)

# et ensuite
Animation.Tout annuler(widget, 'X')

Nouveau dans la version 1.4.0.

Modifié dans la version 2.1.0 : Si le paramètre widget est Aucun, tous les widgets animés seront la
cible et annulés. Sigrands est également donné, l'animation de ces propriétés sera annulée pour tous
les widgets animés.

annuler_propriété(widget, soutenir)
Même si une animation est en cours d'exécution, supprimez une propriété. Il ne sera pas animé davantage.
Si c'était la seule/dernière propriété animée, l'animation sera annulée (voirAnnuler)

Nouveau dans la version 1.4.0.

durée de la propriété
Renvoie la durée de l'animation.
have_properties_to_animer(widget)
Renvoie True si un widget a encore des propriétés à animer.

Nouveau dans la version 1.8.0.

début(widget)
Démarrez l'animation sur un widget.

arrêter(widget)
Arrêter l'animation précédemment appliquée à un widget, déclenchant le on_complete un événement.

stop_all statique(widget, *grands)


Arrêtez toutes les animations qui concernent un widget/une liste de propriétés spécifique.

Exemple:

anime = Animation(X=50)
anime.début(widget)

# et ensuite
Animation.arrête tout(widget, 'X')

stop_propriété(widget, soutenir)
Même si une animation est en cours d'exécution, supprimez une propriété. Il ne sera pas animé davantage.
Si c'était la seule/dernière propriété animée, l'animation sera arrêtée (voirarrêter).

transition de propriété
Renvoie la transition de l'animation.
classer kivy.animation.AnimationTransition
Bases : Builtins.object
Collection de fonctions d'animation à utiliser avec l'objet Animation. Fonctions d'assouplissement portées
sur Kivy à partir du projet Clutterhttps://developer.gnome.org/clutter/stable/ClutterAlpha.html

le le progrès paramètre dans chaque fonction d'animation est dans la plage 0-1.

161
statique à l'arrière(le progrès)

statique in_bounce(le progrès)

statique in_circ(le progrès)

statique in_cubique(le progrès)

statique inélastique(le progrès)

statique in_expo(le progrès)

162
statique in_out_back(le progrès)

statique in_out_bounce(le progrès)

statique in_out_circ(le progrès)

statique in_out_cubique(le progrès)

statique in_out_elastic(le progrès)

statique in_out_expo(le progrès)

163
statique in_out_quad(le progrès)

statique in_out_quart(le progrès)

statique in_out_quint(le progrès)

statique in_out_sine(le progrès)

statique in_quad(le progrès)

statique in_quart(le progrès)

164
statique in_quint(le progrès)

statique in_sine(le progrès)

statique linéaire(le progrès)

statique out_back(le progrès)

statique out_bounce(le progrès)

statique out_circ(le progrès)

165
statique out_cubique(le progrès)

statique out_elastic(le progrès)

statique out_expo(le progrès)

statique out_quad(le progrès)

statique out_quart(le progrès)

statique out_quint(le progrès)

166
statique out_sine(le progrès)

20.3 Candidature

le Application class est la base pour créer des applications Kivy. Considérez-le comme votre principal point d'entrée dans la boucle de
course Kivy. Dans la plupart des cas, vous sous-classez cette classe et créez votre propre application. Vous créez une instance de votre
classe d'application spécifique, puis, lorsque vous êtes prêt à démarrer le cycle de vie de l'application, vous appelez votre instance
App.run() méthode.

20.3.1 Création d'une application

Méthode utilisant build() override

Pour initialiser votre application avec une arborescence de widgets, remplacez le construire() dans votre classe d'application et renvoyez
l'arborescence de widgets que vous avez construite.

Voici un exemple d'application très simple qui n'affiche qu'un bouton :

'''
Exemple d'application utilisant build() + return
==========================================

Une application peut être construite si vous retournez un widget sur build(), ou si vous
→ ensemble
??

auto.racine.
'''

importer kivy
kivy.exiger('1.0.7')

à partir de kivy.app importer Application


à partir de bouton kivy.uix importer Bouton

classer Application de test(Application):

déf construire(soi):
# renvoie un Button() en tant que widget racine
retourner Bouton(texte='Bonjour le monde')

si __Nom__ == '__principale__':
Application de test().Cours()

Le fichier est également disponible dans le dossier des exemples à l'adresse kivy/examples/application/
app_with_build.py.

167
Ici, aucun arbre de widget n'a été construit (ou si vous voulez, un arbre avec uniquement le nœud racine).

Méthode utilisant le fichier kv

Vous pouvez également utiliser le Langue Kivy pour la création d'applications. Le .kv peut contenir des règles et des définitions
de widget racine en même temps. Voici le même exemple que celui de Button dans un fichier kv.

Contenu de 'test.kv' :

# :kivy 1.0

Bouton:
texte: 'Bonjour de test.kv'

Contenu de 'main.py' :

'''
Application construite à partir d'un fichier .kv
===================================

Cela montre comment utiliser implicitement un fichier .kv pour votre application. Vous
devriez voir un bouton en plein écran intitulé "Bonjour de test.kv".

Une fois que Kivy a instancié une sous-classe d'App, il recherche implicitement un fichier .kv.
Le fichier test.kv est sélectionné car le nom de la sous-classe de App

?? est
TestApp, ce qui implique que kivy devrait essayer de charger "test.kv". Ce fichier contient
un widget racine.
'''

importer kivy
kivy.exiger('1.0.7')

à partir de kivy.app importer Application

classer Application de test(Application):

passe

si __Nom__ == '__principale__':
Application de test().Cours()

Voir kivy/examples/application/app_with_kv.py.
La relation entre main.py et test.kv est expliquée dans App.load_kv().

168
20.3.2 Paramétrage des applications

Utiliser le fichier de configuration

Votre application peut avoir besoin de son propre fichier de configuration. leApplication La classe gère automatiquement les
fichiers 'ini' si vous ajoutez la paire clé-valeur de la section au App.build_config() méthode utilisant le configuration paramètre
(une instance de ConfigParser):

classer Application de test(Application):

déf build_config(soi, configuration): configuration.


définir les valeurs par défaut('section 1', {
'clé1': 'valeur1',
'clé2': '42'
})

Dès que vous ajoutez une section à la config, un fichier est créé sur le disque (voir get_application_config
pour son emplacement) et nommé en fonction du nom de votre classe. « TestApp » donnera un fichier de
configuration nommé « test.ini » avec le contenu :

[section 1]
clé1 = valeur1
clé2 = 42

Le « test.ini » sera automatiquement chargé au moment de l'exécution et vous pourrez accéder à la configuration dans votre
App.build() méthode:

classer Application de test(Application):

déf build_config(soi, configuration): configuration.


définir les valeurs par défaut('section 1', {
'clé1': 'valeur1',
'clé2': '42'
})

déf construire(soi):
configuration = soi.configuration
retourner Étiqueter(texte='key1 est %s et key2 est %d' % (
configuration.avoir('section 1', 'clé1'),
configuration.obtenir('section 1', 'clé2')))

169
Créer un panneau de paramètres

Votre application peut avoir un panneau de paramètres pour permettre à votre utilisateur de configurer certains de vos jetons de
configuration. Voici un exemple réalisé dans l'exemple KinectViewer (disponible dans le répertoire des exemples) :

Vous pouvez ajouter vos propres panneaux de paramètres en étendant le App.build_settings() méthode. Vérifier laRéglages
sur la façon de créer un panneau, car vous avez d'abord besoin d'un fichier / de données JSON.

Prenons comme exemple l'extrait précédent de TestApp avec une configuration personnalisée. Nous pourrions créer un JSON comme
ceci :

[
{ "taper": "Titre",
"Titre": "Tester l'application" },

{ "taper": "choix", "Titre": "Ma


première clé",
"desc": "Description de ma première clé", "section":
"section 1", "clé": "clé1",

"options": ["valeur1", "valeur2", "une autre valeur"] },

{ "taper": "numérique", "Titre": "Ma


deuxième clé",
"desc": "Description de ma deuxième clé", "section":
"section 1", "clé": "clé2" }

Ensuite, nous pouvons créer un panneau en utilisant ce JSON pour créer automatiquement toutes les options et les lier à notre
App.config Instance ConfigParser :

classer Application de test(Application):

#...
déf build_settings(soi, réglages):
jsondata = """... mettez les données json ici...""" réglages.
add_json_panel(« Test d'application »,
soi.configuration, Les données=jsondata)

C'est tout! Vous pouvez maintenant appuyer sur F1 (touche par défaut) pour basculer le panneau des paramètres ou appuyer sur la
touche « paramètres » de votre appareil Android. Vous pouvez appeler manuellementApp.open_settings() et App. close_settings()si
vous souhaitez gérer cela manuellement. Chaque changement dans le panneau est automatiquement enregistré dans le fichier de
configuration.

170
Vous pouvez aussi utiliser App.build_settings() pour modifier les propriétés du panneau des paramètres. Par exemple, le
panneau par défaut a une barre latérale pour basculer entre les panneaux json dont la largeur par défaut est 200dp. Si vous
préférez que cela soit plus étroit, vous pouvez ajouter :

réglages.interface.menu.largeur = dp(100)

à ton build_settings() méthode.


Vous voudrez peut-être savoir quand une valeur de configuration a été modifiée par l'utilisateur afin d'adapter ou de recharger votre
interface utilisateur. Vous pouvez alors surcharger leon_config_change() méthode:

classer Application de test(Application):

#...
déf on_config_change(soi, configuration, section, clé, valeur):
si configuration est soi.configuration:
jeton = (section, clé)
si jeton == ('section 1', 'clé1'):
imprimer('Notre clé1 a été changée en', valeur) elif jeton ==
('section 1', 'clé2'):
imprimer('Notre clé2 a été changée en', valeur)

Le panneau de configuration Kivy est ajouté par défaut à l'instance de paramètres. Si vous ne souhaitez pas ce panel, vous
pouvez déclarer votre Application comme suit :

classer Application de test(Application):

use_kivy_settings = Faux
#...

Cela supprime uniquement le panneau Kivy mais n'empêche pas l'instance de paramètres d'apparaître. Si vous souhaitez empêcher
complètement l'instance de paramètres d'apparaître, vous pouvez procéder comme suit :

classer Application de test(Application):

déf open_settings(soi, passe * grands):

Nouveau dans la version 1.0.7.

20.3.3 Profilage avec on_start et on_stop

Il est souvent utile de profiler du code python afin de découvrir des emplacements à optimiser. Les profileurs de
bibliothèque standard (http://docs.python.org/2/library/profile.html) fournit plusieurs options pour le code de profilage.
Pour profiler l'ensemble du programme, les approches naturelles consistant à utiliser profile comme méthode
d'exécution de module ou de profile ne fonctionnent pas avec Kivy. Il est cependant possible d'utiliserApp.on_start() et
App.on_stop() méthodes :

importer cProfil

classer MonApp(Application):
déf on_start(soi): soi.profil = soi.
profil.activer() cProfil.Profil()

déf on_stop(soi): soi.profil.


désactiver()
soi.profil.dump_stats('monapp.profile')

Cela créera un fichier appelé monapplication.profil lorsque vous quittez votre application.

171
20.3.4 Personnalisation de la mise en page

Vous pouvez choisir différentes dispositions de widget de paramètres en définissant App.settings_cls. Par défaut, il
s'agit d'un Réglages classe qui fournit la disposition de la barre latérale illustrée, mais vous pouvez la définir sur l'une
des autres dispositions fournies dans kivy.uix.settings ou créez le vôtre. Voir la documentation du module pour
kivy.uix.settings pour plus d'informations.

Vous pouvez personnaliser l'affichage du panneau des paramètres en remplaçant App.display_settings() qui est appelé avant
d'afficher le panneau des paramètres à l'écran. Par défaut, il dessine simplement le panneau en haut de la fenêtre, mais vous
pouvez le modifier pour (par exemple) afficher les paramètres dans unApparaitre ou ajoutez-le à votre application
Gestionnaire d'écran si vous en utilisez un. Si vous le faites, vous devez également modifierApp. close_settings()pour quitter le
panneau de manière appropriée. Par exemple, pour que le panneau des paramètres apparaisse dans une fenêtre contextuelle,
vous pouvez faire :

déf paramètres d'affichage(soi, réglages):


essayer:
p = soi.settings_popup
à l'exception AttributeError:
soi.settings_popup = Apparaitre(contenu=réglages,
Titre='Réglages', size_hint=(
0,8, 0,8))
p = soi.settings_popup si p.
contenu n'est pas réglages:
p.contenu = réglages
p.ouvert()

déf close_settings(soi, *arguments):


essayer:
p = soi.settings_popup p.
rejeter()
à l'exception AttributeError:
passe # La fenêtre contextuelle des paramètres n'existe pas

Enfin, si vous souhaitez remplacer le widget du panneau de paramètres actuel, vous pouvez supprimer les références
internes à celui-ci en utilisant App.destroy_settings(). Si vous avez modifiéApp.display_settings(), vous devez faire
attention à détecter si le panneau des paramètres a été remplacé.

20.3.5 Mode pause

Nouveau dans la version 1.1.0.

Sur tablettes et téléphones, l'utilisateur peut basculer à tout moment vers une autre application. Par défaut, votre
application se fermera et leApp.on_stop() l'événement sera déclenché.

Si vous prenez en charge le mode Pause, lors du passage à une autre application, votre application attendra
indéfiniment jusqu'à ce que l'utilisateur revienne à votre application. Il y a un problème avec OpenGL sur les appareils
Android : il n'est pas garanti que le contexte OpenGL ES sera restauré lorsque votre application reprendra. Le
mécanisme de restauration de toutes les données OpenGL n'est pas encore implémenté dans Kivy.

Le mécanisme de pause actuellement mis en œuvre est :

1. Kivy vérifie à chaque image si le mode Pause est activé par le système d'exploitation en raison du passage de l'utilisateur à
une autre application, d'un arrêt du téléphone ou pour toute autre raison.

2. App.on_pause() est appelé:


3. Si False est renvoyé, alors App.on_stop() est appelé.

4. Si True est renvoyé (cas par défaut), l'application se mettra en veille jusqu'à ce que le système d'exploitation reprenne notre application.

172
5. Lorsque l'application est reprise, App.on_resume() est appelé.

6. Si la mémoire de notre application a été récupérée par le système d'exploitation, rien ne sera appelé.

Voici un exemple simple d'utilisation de on_pause() :

classer Application de test(Application):

déf on_pause(soi):
# Ici, vous pouvez enregistrer des données si
nécessaire retourner vrai

déf pour résumer(soi):


# Ici, vous pouvez vérifier si des données doivent être remplacées (généralement rien) passe

Avertissement: Les deux on_pause et on_stop doit sauvegarder les données importantes car après on_pause est appelé, pour
résumer peut ne pas être appelé du tout.

20.3.6 Application asynchrone

En plus d'exécuter une application normalement, Kivy peut être exécuté dans une boucle d'événements asynchrone telle que
fournie par le package asyncio de bibliothèque standard ou le package trio (fortement recommandé).

Fond

Normalement, lorsqu'une application Kivy est exécutée, elle bloque le thread qui l'exécute jusqu'à la fermeture de l'application. En interne, à chaque
itération d'horloge, il exécute tous les rappels d'applications, gère les graphiques et les entrées, et se met en veille en dormant pour le temps
restant.

Pour pouvoir s'exécuter de manière asynchrone, l'application Kivy peut ne pas dormir, mais doit à la place libérer le contrôle du
contexte d'exécution à la boucle d'événements asynchrone exécutant l'application Kivy. Nous le faisons lors de l'inactivité en
appelant les fonctions appropriées du package asynchrone utilisé au lieu de dormir.

Configuration asynchrone

Pour exécuter une application Kivy de manière asynchrone, soit le async_runTouchApp() ou App.async_run() coroutine doit
être planifié pour s'exécuter dans la boucle d'événements de la bibliothèque asynchrone utilisée.

La variable environnementaleKIVY_EVENTLOOPou laasync_lib paramètre dans


async_runTouchApp() et App.async_run() définir la bibliothèque asynchrone que Kivy utilise en interne lorsque
l'application est exécutée avec async_runTouchApp() et App.async_run(). Il peut être réglé sur l'un des"asyncio"
quand la bibliothèque standard asynchrone est utilisé, ou "trio" si la bibliothèque trio est utilisée. Si la variable
d'environnement n'est pas définie etasync_lib n'est pas fourni, la stdlib asynchrone est utilisé.

init_async_lib() peut également être appelé directement pour définir l'utilisation de la bibliothèque asynchrone, mais il ne peut être
appelé qu'avant que l'application ne commence à s'exécuter avec async_runTouchApp() ou App.async_run().

Pour exécuter l'application de manière asynchrone, on planifie async_runTouchApp() ou App.async_run() pour s'exécuter dans la boucle
d'événements asynchrone de la bibliothèque donnée, comme dans les exemples ci-dessous. Kivy est alors traité comme une autre
coroutine que la bibliothèque donnée exécute dans sa boucle d'événements. En interne, Kivy utilisera l'API de la bibliothèque asynchrone
spécifiée, doncKIVY_EVENTLOOP ou async_lib doit correspondre à la bibliothèque asynchrone qui exécute Kivy.

Pour des exemples de base plus complets et plus avancés, consultez les applications de démonstration dans exemples/async.

173
Exemple d'Asyncio ~~~~~~~~~~~~~–

importer asynchrone

à partir de kivy.app importer async_runTouchApp à


partir de kivy.uix.label importer Étiqueter

boucler = asynchrone.get_event_loop()
boucler.run_until_complete(
async_runTouchApp(Étiqueter(texte='Bonjour, Monde!'), async_lib='asynchrone'))
boucler.Fermer()

Exemple de trio ~~~~~~~~~~–

importer trio

à partir de kivy.app importer async_runTouchApp à


partir de kivy.uix.label importer Étiqueter

à partir de outils fonctionnels importer partiel

# utilisez functools.partial() pour passer des arguments de mot-clé :


async_runTouchApp_func = partiel(async_runTouchApp, async_lib='trio')

trio.Cours(async_runTouchApp_func, Étiqueter(texte='Bonjour le monde!'))

20.3.7 Interagir avec l'application Kivy à partir d'autres coroutines

Il est totalement sûr d'interagir avec n'importe quel objet kivy d'autres coroutines s'exécutant dans la même boucle
d'événement asynchrone. En effet, ils s'exécutent tous à partir du même thread et les autres coroutines ne sont
exécutées que lorsque Kivy est inactif.

De même, les rappels kivy peuvent interagir en toute sécurité avec des objets d'autres coroutines s'exécutant dans la même boucle
d'événement. Les règles normales à un seul thread s'appliquent dans les deux cas.

Nouveau dans la version 2.0.0.

classer kivy.app.Application(**kwargs)
Bases : kivy.event.EventDispatcher
Classe d'application, voir la documentation du module pour plus d'informations.

Événements

on_start: Lancé au démarrage de l'application (avant le runTouchApp()


appeler.

on_stop: Lancé lorsque l'application s'arrête.

on_pause: Lancé lorsque l'application est interrompue par le système d'exploitation.

pour résumer: Lancé lorsque l'application est reprise après une pause par le système d'exploitation. Faire attention:
vous n'avez aucune garantie que cet événement sera déclenché après le on_pause l'événement a
été appelé.

Modifié dans la version 1.7.0 : Paramètre fichier_kv ajoutée.

Modifié dans la version 1.8.0 : Paramètres fichier_kv et répertoire_kv sont maintenant des propriétés d'App.

174
async async_run(async_lib=Aucun)
Identique à Cours(), mais est une coroutine et peut être planifiée dans une boucle d'événement asynchrone en cours d'exécution.

Voir kivy.app par exemple l'utilisation.

Nouveau dans la version 2.0.0.

construire()
Initialise l'application ; il ne sera appelé qu'une seule fois. Si cette méthode renvoie un widget (arbre),
il sera utilisé comme widget racine et ajouté à la fenêtre.

Retour Aucun ou une racine Widget instance si aucun self.root n'existe.

build_config(configuration)
Nouveau dans la version 1.0.7.

Cette méthode est appelée avant l'initialisation de l'application pour construire votre ConfigParser objet.
C'est ici que vous pouvez mettre n'importe quelle section / clé / valeur par défaut pour votre configuration.
Si quelque chose est défini, la configuration sera automatiquement enregistrée dans le fichier renvoyé par
get_application_config().

Paramètres

configuration: ConfigParser Utilisez ceci pour ajouter des éléments de section/clé/valeur par défaut

build_settings(réglages)
Nouveau dans la version 1.0.7.

Cette méthode est appelée lorsque l'utilisateur (ou vous) souhaitez afficher les paramètres de l'application. Il est appelé
une fois lors de la première ouverture du panneau des paramètres, après quoi le panneau est mis en cache. Il peut être
rappelé si le panneau des paramètres mis en cache est supprimé pardestroy_settings().

Vous pouvez utiliser cette méthode pour ajouter des panneaux de paramètres et pour personnaliser le widget de paramètres, par exemple en

modifiant la largeur de la barre latérale. Consultez la documentation du module pour plus de détails.

Paramètres

réglages: Réglages Instance de paramètres pour l'ajout de panneaux

close_settings(*grand)
Fermez le panneau des paramètres précédemment ouvert.

Retour Vrai si les paramètres ont été fermés.

configuration

Renvoie une instance du ConfigParser pour la configuration de l'application. Vous pouvez l'utiliser pour interroger
certains jetons de configuration dans leconstruire() méthode.

créer_paramètres()
Créez le panneau des paramètres. Cette méthode ne sera normalement appelée qu'une seule fois par durée de vie de
l'application et le résultat est mis en cache en interne, mais elle peut être appelée à nouveau si le panneau mis en cache est
supprimé pardestroy_settings().

Par défaut, il construira un panneau de paramètres selon settings_cls, appeler


build_settings(), ajoutez un panneau Kivy si use_kivy_settings est True et se lie à
on_close/on_config_change.
Si vous souhaitez utiliser votre propre façon de faire les réglages, sans le panneau Kivy ou les événements de changement de
fermeture/configuration, c'est la méthode que vous souhaitez surcharger.

Nouveau dans la version 1.8.0.

détruire_paramètres()
Nouveau dans la version 1.8.0.

Déréférence le panneau de paramètres actuel s'il existe. Cela signifie que lorsque App.
open_settings() est la prochaine exécution, un nouveau panneau sera créé et affiché. Cela n'affecte pas

175
tout le contenu du panneau, mais vous permet (par exemple) d'actualiser la disposition du panneau de paramètres si vous
avez modifié le widget de paramètres en réponse à un changement de taille d'écran.

Si vous avez modifié open_settings() ou paramètres d'affichage(), vous devez veiller à


détecter correctement si le widget de paramètres précédent a été détruit.

répertoire de propriétés
Nouveau dans la version 1.0.7.

Renvoie le répertoire où réside l'application.


paramètres d'affichage(réglages)
Nouveau dans la version 1.8.0.

Affichez le panneau des paramètres. Par défaut, le panneau est dessiné directement au-dessus de la fenêtre. Vous pouvez
définir un autre comportement en remplaçant cette méthode, par exemple en l'ajoutant à un ScreenManager ou à un
Popup.

Vous devez retourner True si l'affichage est réussi, sinon False.


Paramètres

réglages: Réglages Vous pouvez modifier cet objet afin de modifier les paramètres
affichage.

get_application_config(defaultpath='%(appdir)s/%(appname)s.ini')
Renvoyez le nom de fichier de la configuration de votre application. Selon la plateforme, le dossier de
candidature sera stocké à différents emplacements :

• sur iOS : <appdir>/Documents/.<appname>.ini


• sur Android : <user_data_dir>/.<appname>.ini
• sinon : <appdir>/<appname>.ini
Lorsque vous distribuez votre application sur des postes de travail, veuillez noter que si l'application est destinée à être
installée à l'échelle du système, l'utilisateur peut ne pas avoir accès en écriture au répertoire de l'application. Si vous
souhaitez stocker les paramètres utilisateur, vous devez surcharger cette méthode et modifier le comportement par défaut
pour enregistrer le fichier de configuration dans le répertoire utilisateur.

classer Application de test(Application):

déf get_application_config(soi):
retourner super(Application de test, soi).get_application_config(
'~/.%(appname)s.ini')

Quelques notes:

• Le tilda '~' sera étendu au répertoire utilisateur.


• %(appdir)s sera remplacé par l'application annuaire
• %(appname)s sera remplacé par l'application Nom
Nouveau dans la version 1.0.7.

Modifié dans la version 1.4.0 : Personnalisation du chemin par défaut pour les plates-formes iOS et Android. Ajout d'un
paramètre defaultpath pour les systèmes d'exploitation de bureau (ne s'applique pas à iOS et Android.)

Modifié dans la version 1.11.0 : Modification de la version Android pour utiliser le user_data_dir et a
ajouté un point manquant au nom du fichier de configuration iOS.

get_application_icon()
Renvoie l'icône de l'application.
get_application_name()
Renvoie le nom de l'application.

176
get_running_app statique()
Renvoie l'instance d'application en cours d'exécution.

Nouveau dans la version 1.1.0.

icône
Icône de votre application. L'icône peut être située dans le même répertoire que votre fichier principal. Vous
pouvez le définir comme suit :

classer MonApp(Application):
déf construire(soi):
soi.icône = 'myicon.png'

Nouveau dans la version 1.0.5.

Modifié dans la version 1.8.0 : icône est maintenant un Propriété de chaîne. Ne définissez pas l'icône dans la classe comme
indiqué précédemment dans la documentation.

Noter: Pour Kivy avant la version 1.8.0, vous devez définir ceci comme suit :

classer MonApp(Application):
icône = 'customicon.png'

Recommandé 256x256 ou 1024x1024 ? pour GNU/Linux et Mac OSX 32x32 pour Windows7 ou moins.
<= 256x256 pour Windows 8 256x256 fonctionne (au moins sur Windows 8), mais est réduit et n'a pas
l'air aussi beau qu'une icône 32x32.

répertoire_kv
Chemin du répertoire où l'application kv est stockée, par défaut Aucun

Nouveau dans la version 1.8.0.

Si un kv_directory est défini, il sera utilisé pour obtenir le fichier kv initial. Par défaut, le fichier est supposé se trouver dans
le même répertoire que le fichier de définition d'application actuel.

fichier_kv
Nom de fichier du fichier Kv à charger, par défaut Aucun.

Nouveau dans la version 1.8.0.

Si un fichier kv_file est défini, il sera chargé au démarrage de l'application. Le chargement du fichier kv « par
défaut » sera empêché.

load_config()
(interne) Cette fonction permet de renvoyer un ConfigParser avec la configuration de
l'application. Il fait 3 choses :

1. Création d'une instance d'un ConfigParser

2. Chargement de la configuration par défaut en appelant build_config(), ensuite

3. S'il existe, il charge le fichier de configuration de l'application, sinon il en crée un.

Retour ConfigParser exemple

charge_kv(nom de fichier=Aucun)
Cette méthode est invoquée la première fois que l'application est exécutée si aucune arborescence de widgets n'a été
construite auparavant pour cette application. Cette méthode recherche ensuite un fichier kv correspondant dans le même
répertoire que le fichier contenant la classe d'application.

Par exemple, supposons que vous ayez un fichier nommé main.py qui contient :

177
classer ShowcaseApp(Application):
passe

Cette méthode recherchera un fichier nommé vitrine.kv dans le répertoire qui contient main.py.
Le nom du fichier kv doit être le nom en minuscule de la classe, sans le suffixe 'App' à la fin s'il
existe.

Vous pouvez définir des règles et un widget racine dans votre fichier kv :

<Nom du cours>: # c'est une règle


...

Nom du cours: # c'est un widget racine


...

Il ne doit y avoir qu'un seul widget racine. Voir leLangue Kivy documentation pour plus d'informations
sur la création de fichiers kv. Si votre fichier kv contient un widget racine, il sera utilisé comme
self.root, le widget racine de l'application.

Noter: Cette fonction est appelée à partir de Cours(), par conséquent, tout widget dont le style est défini
dans ce fichier kv et est créé avant Cours() est appelé (par exemple dans __init__), n'aura pas son style
appliqué. Noter queconstruire() est appelé après charge_kv a été appelé.

nom de la propriété
Nouveau dans la version 1.0.7.

Renvoie le nom de l'application en fonction du nom de la classe.

on_config_change(configuration, section, clé, valeur)


Gestionnaire d'événements déclenché lorsqu'un jeton de configuration a été modifié par la page des paramètres.

Modifié dans la version 1.10.1 : Ajout correspondant on_config_change un événement.

on_pause()
Gestionnaire d'événements appelé lorsque le mode Pause est demandé. Vous devez retourner True si votre
application peut passer en mode Pause, sinon retourner False et votre application sera arrêtée.

Vous ne pouvez pas contrôler quand l'application va passer dans ce mode. Il est déterminé par le système
d'exploitation et principalement utilisé pour les appareils mobiles (android/ios) et pour le redimensionnement.

La valeur de retour par défaut est True.

Nouveau dans la version 1.1.0.

Modifié dans la version 1.10.0 : la valeur de retour par défaut est désormais True.

pour résumer()
Gestionnaire d'événements appelé lorsque votre application sort du mode Pause.

Nouveau dans la version 1.1.0.

Avertissement: Lors de la reprise, le contexte OpenGL peut avoir été endommagé/libéré. C'est là que vous
pouvez reconstruire une partie de votre état OpenGL, par exemple le contenu FBO.

on_start()
Gestionnaire d'événements pour le on_start événement qui est déclenché après l'initialisation (après que build() a été
appelé) mais avant que l'application n'ait commencé à s'exécuter.

178
on_stop()
Gestionnaire d'événements pour le on_stop événement qui est déclenché lorsque l'application a fini de s'exécuter (c'est-à-
dire que la fenêtre est sur le point d'être fermée).

open_settings(*grand)
Ouvrez le panneau des paramètres de l'application. Il sera créé la toute première fois, ou recréé si le
panneau précédemment mis en cache a été supprimé pardestroy_settings(). Le panneau des
paramètres s'affichera avec leparamètres d'affichage() méthode, qui ajoute par défaut le panneau
des paramètres à la fenêtre attachée à votre application. Vous devez remplacer cette méthode si vous
souhaitez afficher le panneau des paramètres différemment.

Retour Vrai si les paramètres ont été ouverts.

options
Options passées au __init__ de l'App
racine
le racine widget renvoyé par le construire() méthode ou par le load_kv() méthode si le fichier kv
contient un widget racine.

propriété root_window
Nouveau dans la version 1.9.0.

Renvoie l'instance de fenêtre racine utilisée par Cours().

Cours()
Lance l'application en mode autonome.

settings_cls
Nouveau dans la version 1.8.0.

La classe utilisée pour construire le panneau des paramètres et l'instance passée à build_config(). Vous
devez utiliser soitRéglages ou l'une des sous-classes fournies avec des mises en page différentes (
ParamètresAvec Barre Latérale, ParamètresAvecSpinner, ParamètresAvecTabbedPanel,
ParamètresAvecNoMenu). Vous pouvez également créer votre propre sous-classe Settings. Voir la
documentation deRéglages pour plus d'informations.

settings_cls est un Propriété de l'objet et par défaut à ParamètresAvecSpinner qui affiche des
panneaux de paramètres avec une flèche pour basculer entre eux. Si vous définissez une chaîne, le
Usine sera utilisé pour résoudre la classe.

arrêter(*grand)
Arrêtez l'application.

Si vous utilisez cette méthode, toute l'application s'arrêtera en appelant à stopTouchApp().

Titre
Titre de votre candidature. Vous pouvez le définir comme suit :

classer MonApp(Application):
déf construire(soi):
soi.Titre = 'Bonjour le monde'

Nouveau dans la version 1.0.5.

Modifié dans la version 1.8.0 : Titre est maintenant un Propriété de chaîne. Ne définissez pas le titre dans la classe comme
indiqué précédemment dans la documentation.

Noter: Pour Kivy < 1.8.0, vous pouvez définir ceci comme suit :

classer MonApp(Application):
Titre = 'Titre personnalisé'

179
Si vous souhaitez modifier dynamiquement le titre, vous pouvez faire :

à partir de kivy.base importer EventLoop


EventLoop.la fenêtre.Titre = "Nouveau titre"

use_kivy_settings = Vrai
Nouveau dans la version 1.0.7.

Si True, les paramètres de l'application incluront également les paramètres Kivy. Si vous ne souhaitez pas que l'utilisateur modifie les
paramètres de Kivy à partir de votre interface utilisateur de paramètres, définissez-le sur False.

propriété user_data_dir
Nouveau dans la version 1.7.0.

Renvoie le chemin d'accès au répertoire dans le système de fichiers des utilisateurs que l'application peut utiliser pour stocker des
données supplémentaires.

Différentes plates-formes ont des conventions différentes en ce qui concerne l'endroit où l'utilisateur peut stocker
des données telles que les préférences, les jeux enregistrés et les paramètres. Cette fonction implémente ces
conventions. Le répertoire <app_name> est créé lorsque la propriété est appelée, sauf s'il existe déjà.

Sur iOS, ~/Documents/<nom_application> est renvoyé (qui se trouve dans le bac à sable de l'application).

Sous Windows, %APPDATA%/<app_name> est retourné.

Sous OS X, ~/Bibliothèque/Application Support/<app_name> est retourné.

Sous Linux, $XDG_CONFIG_HOME/<nom_application> est retourné.

Sur Androïd, Context.GetFilesDir est retourné.

Modifié dans la version 1.11.0 : Sur Android, cette fonction revenait auparavant /sdcard/<app_name>.
Ce dossier est devenu en lecture seule par défaut dans Android API 26 et le user_data_dir a donc été
déplacé vers un emplacement accessible en écriture.

asynchrone kivy.app.async_runTouchApp(widget=Aucun, embarqué=Faux, async_lib=Aucun)


Identique à runTouchApp() mais à la place, c'est une coroutine qui peut être exécutée dans une boucle d'événement asynchrone
existante.

async_lib est la bibliothèque async à utiliser. Voirkivy.app pour plus de détails et des exemples d'utilisation.

Nouveau dans la version 2.0.0.

kivy.app.exécuterTouchApp(widget=Aucun, embarqué=Faux)
Fonction principale statique qui démarre la boucle d'application. Vous pouvez accéder à de la magie via les arguments
suivants :

Voir kivy.app par exemple l'utilisation.

Paramètres

<vide> Pour que la répartition fonctionne, vous avez besoin d'au moins un écouteur d'entrée. Si non,
l'application partira. (MTWindow agit comme un écouteur d'entrée)

widget Si vous ne passez qu'un widget, une MTWindow sera créée et votre widget
sera ajouté à la fenêtre en tant que widget racine.

embarqué Aucun envoi d'événement n'est effectué. Ce sera votre travail.

widget + intégré Aucun envoi d'événement n'est effectué. Ce sera votre travail mais nous essayons
pour obtenir la fenêtre (doit être créée par vous au préalable) et y ajouter le widget.
Très utile pour intégrer Kivy dans une autre boîte à outils. (comme Qt, vérifiez
kivydesigned)

180
kivy.app.stopTouchApp()
Arrêtez l'application en cours en quittant la boucle principale.

Voir kivy.app par exemple l'utilisation.

20.4 Chargeur de données asynchrone

C'est le chargeur asynchrone. Vous pouvez l'utiliser pour charger une image et l'utiliser, même si les données ne sont pas encore
disponibles. Vous devez spécifier une image de chargement par défaut lors de l'utilisation du chargeur :

à partir de kivy.loader importer Image du


chargeur = Chargeur.image('mysprite.png')

Vous pouvez également charger une image à partir d'une URL :

image = Chargeur.image('http://monsite.com/test.png')

Si vous souhaitez modifier l'image de chargement par défaut, vous pouvez faire :

Chargeur.chargement_image = Image('un autre_chargement.png')

20.4.1 Peaufiner le chargeur asynchrone

Nouveau dans la version 1.6.0.

Vous pouvez modifier le chargeur pour offrir une meilleure expérience utilisateur ou plus de performances, en fonction
des images que vous allez charger. Regarde les paramètres :

• Loader.num_workers - définir le nombre de threads à démarrer pour le chargement des images.

• Loader.max_upload_per_frame - définir le nombre maximal de téléchargements d'images dans le GPU à effectuer par
image.

classer kivy.loader.ChargeurBase
Bases : Builtins.object
Base commune pour le Loader et implémentations spécifiques. Par défaut, le Loader sera la meilleure
implémentation de loader disponible.

La fonction _update() est appelée toutes les 1/25.s ou à chaque frame si nous avons moins de 25 FPS.

propriété error_image
Image utilisée pour l'erreur. Vous pouvez le changer en faisant :

Chargeur.Erreur d'image = 'erreur.png'

Modifié dans la version 1.6.0 : n'est plus en lecture seule.

image(nom de fichier, load_callback=Aucun, post_callback=Aucun, **kwargs)


Load a image using the Loader. A ProxyImage is returned with a loading image. You can use it
as follows:

from kivy.app import App from


kivy.uix.image import Image from
kivy.loader import Loader

class TestApp(App):
def _image_loaded(self, proxyImage):
(continues on next page)

181
(continued from previous page)

if proxyImage.image.texture:
self.image.texture = proxyImage.image.texture

def build(self):
proxyImage = Loader.image("myPic.jpg")
proxyImage.bind(on_load=self._image_loaded) self.image
= Image() return self.image

TestApp().run()

In order to cancel all background loading, call Loader.stop().

property loading_image
Image used for loading. You can change it by doing:

Loader.loading_image = 'loading.png'

Changed in version 1.6.0: Not readonly anymore.

property max_upload_per_frame
The number of images to upload per frame. By default, we’ll upload only 2 images to the GPU
per frame. If you are uploading many small images, you can easily increase this parameter to 10
or more. If you are loading multiple full HD images, the upload time may have consequences
and block the application. If you want a smooth experience, use the default.

As a matter of fact, a Full-HD RGB image will take ~6MB in memory, so it may take time. If you
have activated mipmap=True too, then the GPU must calculate the mipmap of these big images
too, in real time. Then it may be best to reduce the max_upload_per_frame to 1 or 2. If you
want to get rid of that (or reduce it a lot), take a look at the DDS format.

New in version 1.6.0.

property num_workers
Number of workers to use while loading (used only if the loader implementation supports it).
This setting impacts the loader only on initialization. Once the loader is started, the setting has
no impact:

from kivy.loader import Loader Loader.


num_workers = 4

The default value is 2 for giving a smooth user experience. You could increase the number of
workers, then all the images will be loaded faster, but the user will not been able to use the
application while loading. Prior to 1.6.0, the default number was 20, and loading many full-hd
images was completely blocking the application.

New in version 1.6.0.

pause()
Pause the loader, can be useful during interactions.

New in version 1.6.0.

resume()
Resume the loader, after a pause().

New in version 1.6.0.

run(*largs)
Main loop for the loader.

182
start()
Start the loader thread/process.

stop()
Stop the loader thread/process.

class kivy.loader.ProxyImage(arg, **kwargs)


Bases: kivy.core.image.Image
Image returned by the Loader.image() function.

Properties

loaded: bool, defaults to False This value may be True if the image is already
cached.

Events

on_load Fired when the image is loaded or changed.


on_error Fired when the image cannot be loaded. error: Exception data that oc-
curred

20.5 Atlas

New in version 1.1.0.

Atlas manages texture atlases: packing multiple textures into one. With it, you reduce the number of
images loaded and speedup the application loading. This module contains both the Atlas class and
command line processing for creating an atlas from a set of individual PNG files. The command line section
requires the Pillow library, or the defunct Python Imaging Library (PIL), to be installed.

An Atlas is composed of 2 or more files:

• a json file (.atlas) that contains the image file names and texture locations of the atlas.

• one or multiple image files containing textures referenced by the .atlas file.

20.5.1 Definition of .atlas files

A file with <basename>.atlas is a json file formatted like this:

{
"<basename>-<index>.png": {
"id1": [ <x>, <y>, <width>, <height> ], "id2": [ <x>, <y>
, <width>, <height> ],
#...
},
#...
}

Example from the Kivy data/images/defaulttheme.atlas:

{
"defaulttheme-0.png": {
"progressbar_background": [431, 224, 59, 24], "image-
missing": [253, 344, 48, 48], "filechooser_selected": [1, 207,
118, 118], "bubble_btn": [83, 174, 32, 32],

(continues on next page)

183
(continued from previous page)

# . . . and more ...


}
}

In this example, “defaulttheme-0.png” is a large image, with the pixels in the rectangle from (431,
224) to (431 + 59, 224 + 24) usable as atlas://data/images/defaulttheme/ progressbar_background in
any image parameter.

20.5.2 How to create an Atlas

Warning: The atlas creation requires the Pillow library (or the defunct Imaging/PIL library). This
requirement will be removed in the future when the Kivy core Image is able to support loading, blitting,
and saving operations.

You can directly use this module to create atlas files with this command:

$ python -m kivy.atlas <basename> <size> <list of images...>

Let’s say you have a list of images that you want to put into an Atlas. The directory is named images with
lots of 64x64 png files inside:

$ ls
images
$ cd images
$ ls
bubble.png bubble-red.png button.png button-down.png

You can combine all the png’s into one and generate the atlas file with:

$ python -m kivy.atlas myatlas 256x256 *.png Atlas created


at myatlas.atlas
1 image has been created $ ls

bubble.png bubble-red.png button.png button-down.png myatlas.atlas myatlas-0.png

As you can see, we get 2 new files: myatlas.atlas and myatlas-0.png. myatlas-0.png is a new
256x256 .png composed of all your images. If the size you specify is not large enough to fit all of the
source images, more atlas images will be created as required e.g. myatlas-1.png, myatlas-2.png etc.

Note: When using this script, the ids referenced in the atlas are the base names of the images without the
extension. So, if you are going to name a file ../images/button.png, the id for this image will be button.

If you need path information included, you should include use_path as follows:

$ python -m kivy.atlas -- --use_path myatlas 256 *.png

In which case the id for ../images/button.png will be images_button

184
20.5.3 How to use an Atlas

Usually, you would specify the images by supplying the path:

a = Button(background_normal='images/button.png',
background_down='images/button_down.png')

In our previous example, we have created the atlas containing both images and put them in images/
myatlas.atlas. You can use url notation to reference them:

a = Button(background_normal='atlas://images/myatlas/button',
background_down='atlas://images/myatlas/button_down')

In other words, the path to the images is replaced by:

atlas://path/to/myatlas/id
# will search for the ``path/to/myatlas.atlas`` and get the image ``id``

Note: In the atlas url, there is no need to add the .atlas extension. It will be automatically append to the
filename.

20.5.4 Manual usage of the Atlas

> > > from kivy.atlas import Atlas


> > > atlas = Atlas('path/to/myatlas.atlas')
> > > print(atlas.textures.keys())
['bubble', 'bubble-red', 'button', 'button-down']
> > > print(atlas['button']) <kivy.graphics.texture.TextureRegion object at
0x2404d10>

class kivy.atlas.Atlas(filename)
Bases: kivy.event.EventDispatcher
Manage texture atlas. See module documentation for more information.

static create(outname, filenames, size, padding=2, use_path=False)


This method can be used to create an atlas manually from a set of images.

Parameters

outname: str Basename to use for .atlas creation and -<idx>.png associ-
ated images.

filenames: list List of filenames to put in the atlas.


size: int or list (width, height) Size of the atlas image. If the size is not large
enough to fit all of the source images, more atlas images will created as
required.

padding: int, defaults to 2 Padding to put around each image.


Be careful. If you’re using a padding < 2, you might have issues with the borders
of the images. Because of the OpenGL linearization, it might use the pixels of the
adjacent image.

If you’re using a padding >= 2, we’ll automatically generate a “border” of 1px


around your image. If you look at the result, don’t be scared if the image inside is
not exactly the same as yours :).

185
use_path: bool, defaults to False If True, the relative path of the source png file
names will be included in the atlas ids rather that just in the file names.
Leading dots and slashes will be excluded and all other slashes in the path
will be replaced with underscores. For example, if use_path is False (the
default) and the file name is ../data/tiles/green_grass.png, the id will be
green_grass. If use_path is True, it will be data_tiles_green_grass.
Changed in version 1.8.0: Parameter use_path added

filename
Filename of the current Atlas.

filename is an AliasProperty and defaults to None.


original_textures
List of original atlas textures (which contain the textures).
original_textures is a ListProperty and defaults to [].
New in version 1.9.1.

textures
List of available textures within the atlas.

textures is a DictProperty and defaults to {}.

20.6 Cache manager

The cache manager can be used to store python objects attached to a unique key. The cache can be
controlled in two ways: with a object limit or a timeout.

For example, we can create a new cache with a limit of 10 objects and a timeout of 5 seconds:

# register a new Cache


Cache.register('mycache', limit=10, timeout=5)

# create an object + id key =


'objectid'
instance = Label(text=text) Cache.
append('mycache', key, instance)

# retrieve the cached object instance = Cache.


get('mycache', key)

If the instance is NULL, the cache may have trashed it because you’ve not used the label for 5 seconds and
you’ve reach the limit.

class kivy.cache.Cache
Bases: builtins.object
See module documentation for more information.

static append(category, key, obj, timeout=None)


Add a new object to the cache.

Parameters

category: str Identifier of the category.

key: str Unique identifier of the object to store.


obj: object Object to store in cache.

186
timeout: double (optional) Time after which to delete the object if it has not
been used. If None, no timeout is applied.

Raises ValueError: If None is used as key.

Changed in version 2.0.0: Raises ValueError if None is used as key.

static get(category, key, default=None)


Get a object from the cache.

Parameters

category: str Identifier of the category.

key: str Unique identifier of the object in the store.


default: anything, defaults to None Default value to be returned if the key is
not found.

static get_lastaccess(category, key, default=None)


Get the objects last access time in the cache.

Parameters

category: str Identifier of the category.

key: str Unique identifier of the object in the store.


default: anything, defaults to None Default value to be returned if the key is
not found.

static get_timestamp(category, key, default=None)


Get the object timestamp in the cache.

Parameters

category: str Identifier of the category.

key: str Unique identifier of the object in the store.


default: anything, defaults to None Default value to be returned if the key is
not found.

static print_usage()
Print the cache usage to the console.

static register(category, limit=None, timeout=None)


Register a new category in the cache with the specified limit.

Parameters

category: str Identifier of the category.

limit: int (optional) Maximum number of objects allowed in the cache. If None,
no limit is applied.

timeout: double (optional) Time after which to delete the object if it has not
been used. If None, no timeout is applied.

static remove(category, key=None)


Purge the cache.

Parameters

category: str Identifier of the category.

key: str (optional) Unique identifier of the object in the store. If this argument
is not supplied, the entire category will be purged.

187
20.7 Clock object

The Clock object allows you to schedule a function call in the future; once or repeatedly at specified
intervals. You can get the time elapsed between the scheduling and the calling of the callback via the dt
argument:

# dt means delta-time
def my_callback(dt): pass

# call my_callback every 0.5 seconds Clock.


schedule_interval(my_callback, 0.5)

# call my_callback in 5 seconds Clock.


schedule_once(my_callback, 5)

# call my_callback as soon as possible (usually next frame.) Clock.


schedule_once(my_callback)

Note: If the callback returns False, the schedule will be canceled and won’t repeat.

If you want to schedule a function to call with default arguments, you can use the functools.partial python
module:

from functools import partial

def my_callback(value, key, *largs):


pass

Clock.schedule_interval(partial(my_callback, 'my value', 'my key'), 0.5)

Conversely, if you want to schedule a function that doesn’t accept the dt argument, you can use a lambda
expression to write a short function that does accept dt. For Example:

def no_args_func():
print("I accept no arguments, so don't schedule me in the clock")

Clock.schedule_once(lambda dt: no_args_func(), 0.5)

Note: You cannot unschedule an anonymous function unless you keep a reference to it. It’s better to add
*args to your function definition so that it can be called with an arbitrary number of parameters.

Important: The class method callback is weak-referenced: you are responsible for keeping a reference to
your original object/callback. If you don’t keep a reference, the ClockBase will never execute your callback.
For example:

class Foo(object):
def start(self):
Clock.schedule_interval(self.callback, 0.5)

def callback(self, dt):


(continues on next page)

188
(continued from previous page)

print('In callback')

# A Foo object is created and the method start is called.


# Because no reference is kept to the instance returned from Foo(),
# the object will be collected by the Python Garbage Collector and
# your callback will be never called. Foo().start()

# So you should do the following and keep a reference to the instance


# of foo until you don't need it anymore! foo = Foo()

foo.start()

20.7.1 Schedule before frame

New in version 1.0.5.

Sometimes you need to schedule a callback BEFORE the next frame. Starting from 1.0.5, you can use a
timeout of -1:

Clock.schedule_once(my_callback, 0) # call after the next frame Clock.schedule_once(


my_callback, -1) # call before the next frame

The Clock will execute all the callbacks with a timeout of -1 before the next frame even if you add a new
callback with -1 from a running callback. However, Clock has an iteration limit for these callbacks: it
defaults to 10.

If you schedule a callback that schedules a callback that schedules a . . . etc more than 10 times, it will
leave the loop and send a warning to the console, then continue after the next frame. This is
implemented to prevent bugs from hanging or crashing the application.
If you need to increase the limit, set the max_iteration property:

from kivy.clock import Clock Clock.


max_iteration = 20

20.7.2 Triggered Events

New in version 1.0.5.

CyClockBase.create_trigger() is an advanced method way to defer a callback. It functions exactly like


CyClockBase.schedule_once() and CyClockBase.schedule_interval() except that it doesn’t
immediately schedule the callback. Instead, one schedules the callback using the ClockEvent
returned by it. This ensures that you can call the event multiple times but it won’t be scheduled more
than once. This is not the case with CyClockBase.schedule_once():

# will run the callback twice before the next frame Clock.
schedule_once(my_callback) Clock.schedule_once(my_callback)

# will run the callback once before the next frame event =
Clock.create_trigger(my_callback)
event()
(continues on next page)

189
(continued from previous page)

event()

# will also run the callback only once before the next frame event = Clock.
schedule_once(my_callback) event() # now it's already scheduled
# won't be scheduled again
event()

In addition, it is more convenient to create and bind to the triggered event than using CyClockBase.
schedule_once() in a function:

from kivy.clock import Clock from


kivy.uix.widget import Widget

class Sample(Widget):
def __init__(self, self. * *kwargs):
_trigger = Clock.create_trigger(self.cb) self).__init__
super(Sample, (**kwargs)
self.bind(x=self._trigger, y=self._trigger)

def cb(self, *largs): pass

Even if x and y changes within one frame, the callback is only run once.

20.7.3 Unscheduling

An event scheduled with CyClockBase.schedule_once(), CyClockBase.


schedule_interval(), or with CyClockBase.create_trigger() and then triggered can be unscheduled
in multiple ways. E.g:

def my_callback(dt): pass

# call my_callback every 0.5 seconds


event = Clock.schedule_interval(my_callback, 0.5)

# call my_callback in 5 seconds


event2 = Clock.schedule_once(my_callback, 5)

event_trig = Clock.create_trigger(my_callback, 5) event_trig()

# unschedule using cancel event


.cancel()

# unschedule using Clock.unschedule Clock.


unschedule(event2)

# unschedule using Clock.unschedule with the callback


# NOT RECOMMENDED
Clock.unschedule(my_callback)

The best way to unschedule a callback is with ClockEvent.cancel(). unschedule() is mainly


CyClockBase.
an alias
for that for that function. However, if the original callback itself

190
is passed to CyClockBase.unschedule(), it’ll unschedule all instances of that callback (provided all is
True, the default, otherwise only the first match is removed).
Calling CyClockBase.unschedule() on the original callback is highly discouraged because it’s
significantly slower than when using the event.

20.7.4 Clock Lifecycle

Kivy’s clock has a lifecycle. By default, scheduling a callback after the Clock has ended will not raise an
error, even though the callback may never be called. That’s because most callbacks are like services, e.g.
responding to a user button press - if the app is running the callbacks need to service the app and respond
to the input, but once the app has stopped or is stopping, we can safely not process these events.

Other events always need to be processed. E.g. another thread may request a callback in kivy’s thread and
then process some result. If the event is not processed in Kivy’s thread because the app stopped, the
second thread may block forever hanging the application as it exits.

Consequently, we provide a API (CyClockBase.create_lifecycle_aware_trigger()) for scheduling


callbacks that raise a ClockNotRunningError if the clock has stopped. If the scheduling succeeded it
guarantees that one of its callbacks will be called. I.e. the new CyClockBase.
create_lifecycle_aware_trigger() accepts an additional clock_ended_callback parameter. Normally,
callback will be called when the event is processed. But, if the clock is stopped before it can be
processed, if the application exited normally (and the app was started) and the event wasn’t canceled,
and the callbacks are not garbage collected, then clock_ended_callback will be called instead when
the clock is stopped.
That is, given these conditions, if ClockNotRunningError was not raised when the event was
scheduled, then one of these callbacks will be called - either callback if the event executed normally,
or clock_ended_callback if the clock is stopped while the event is scheduled.
By default, events can be scheduled before the clock is started because it is assumed the clock will
eventually be started when the app starts. I.e. calling CyClockBase. create_lifecycle_aware_trigger()
before the clock and application starts will succeed. But if the app never actually starts, then neither
of the callbacks may be executed.
New in version 2.0.0: The lifecycle was added in 2.0.0

20.7.5 Exception Handling

Kivy provides a exception handling manager, ExceptionManager, to handle its internal exceptions
including exceptions raised by clock callbacks, without crashing the application. By default when an
exception is raised, the app will crash. But, if a handler is registered with the exception manager and the
handler handles the exception, the app will not crash and will continue as normal.:

from kivy.base import ExceptionHandler, ExceptionManager class


MyHandler(ExceptionHandler):
def handle_exception(self, inst): if isinstance(
inst, ValueError):
Logger.exception('ValueError caught by MyHandler') return
ExceptionManager.PASS return ExceptionManager.RAISE

ExceptionManager.add_handler(MyHandler())

Then, all ValueError exceptions will be logged to the console and ignored. Similarly, if a scheduled clock
callback raises a ValueError, other clock events will still be processed normally.

191
If an event’s callback raises an exception, before the exception handler is executed, the callback is
immediately canceled.

It still is possible for the app to be corrupted if kivy itself is the source of the exception. I.e. even with a
handler that ignores exceptions and doesn’t crash, the app may be in a corrupted state if the error
originates from within Kivy itself. However, the exception handler can help protect the app from crashing
and can help protect against user callbacks crashing the app.

Changed in version 2.0.0: Prior to Kivy 2.0.0, an exception raised in a event’s callback would cause the clock
to crash and subsequent events may or may not be executed. Even if the exception was handled by an
ExceptionHandler, there was no guarantee that some scheduled events would not be skipped.
From 2.0.0 onward, if a event’s exception is handled by an ExceptionHandler, other events will be shielded
from the exception and will execute normally.

20.7.6 Scheduling from __del__

It is not safe to schedule Clock events from a object’s __del__ or __dealloc__ method. If you must
schedule a Clock call from this method, use CyClockBase.schedule_del_safe() or
CyClockBase.schedule_lifecycle_aware_del_safe() instead.

20.7.7 Threading and Callback Order

Beginning with 1.10.0, all the events scheduled for the same frame, e.g. all the events scheduled in the
same frame with a timeout of 0, well be executed in the order they were scheduled.

Also, all the scheduling and canceling methods are fully thread safe and can be safely used from external
threads.

As a a consequence, calling CyClockBase.unschedule() with the original callback is now significantly


slower and highly discouraged. Instead, the returned events should be used to cancel. As a tradeoff,
all the other methods are now significantly faster than before.

20.7.8 Advanced Clock Details

The following section goes into the internal kivy clock details as well as the various clock options. It is
meant only for advanced users.

Fundamentally, the Kivy clock attempts to execute any scheduled callback rhythmically as determined by
the specified fps (frame per second, see maxfps in config). That is, ideally, given e.g. a desired fps of 30,
the clock will execute the callbacks at intervals of 1 / 30 seconds, or every 33.33 ms. All the callbacks in a
frame are given the same timestamp, i.e. the dt passed to the callback are all the same and it’s the
difference in time between the start of this and the previous frame.

Because of inherent indeterminism, the frames do not actually occur exactly at intervals of the fps and dt
may be under or over the desired fps. Also, once the timeout is “close enough” to the desired timeout, as
determined internally, Kivy will execute the callback in the current frame even when the “actual time” has
not elapsed the timeout amount.

Kivy offers now, since 1.10.0, multiple clocks with different behaviors.

192
Default Clock

The default clock (default) behaves as described above. When a callback with a timeout of zero or non-zero
is scheduled, they are executed at the frame that is near the timeout, which is a function of the fps. So a
timeout of zero would still result in a delay of one frame or about 1 / fps, typically a bit less but sometimes
more depending on the CPU usage of the other events scheduled for that frame.

In a test using a fps of 30, a callback with a timeout of 0, 0.001, and 0.05, resulted in a mean callback delay
of 0.02487, 0.02488, and 0.05011 seconds, respectively. When tested with a fps of 600 the delay for 0.05
was similar, except the standard deviation was reduced resulting in overall better accuracy.

Interruptible Clock

The default clock suffers from the quantization problem, as frames occur only on intervals and any
scheduled timeouts will not be able to occur during an interval. For example, with the timeout of 0.05,
while the mean was 0.05011, its values ranged between 0.02548 - 0.07348 and a standard deviation of
0.002. Also, there’s the minimum timeout of about 0.02487.

The interruptible clock (interrupt) will execute timeouts even during a frame. So a timeout of zero will
execute as quickly as possible and similarly a non-zero timeout will be executed even during the interval.

This clock, and all the clocks described after this have an option, ClockBaseInterruptBehavior.
interupt_next_only. When True, any of the behavior new behavior will only apply to the callbacks with
a timeout of zero. Non-zero timeouts will behave like in the default clock. E.g. for this clock when
True, only zero timeouts will execute during the the interval.
In a test using a fps of 30, a callback with a timeout of 0, 0.001, and 0.05, resulted in a mean callback
delay of 0.00013, 0.00013, and 0.04120 seconds, respectively when ClockBaseInterruptBehavior.
interupt_next_only was False. Also, compared to the default clock the standard deviation was
reduced. When ClockBaseInterruptBehavior.interupt_next_only was True, the values were 0.00010,
0.02414, and 0.05034, respectively.

Free Clock

The interruptible clock may not be ideal for all cases because all the events are executed during the
intervals and events are not executed anymore rhythmically as multiples of the fps. For example, there
may not be any benefit for the graphics to update in a sub-interval, so the additional accuracy wastes CPU.

The Free clock (free_all) solves this by having Clock.xxx_free versions of all the Clock scheduling
methods. By free, we mean the event is free from the fps because it’s not fps limited. E.g.
CyClockBaseFree.create_trigger_free() corresponds to CyClockBase.
create_trigger(). Only when an event scheduled using the Clock.xxx_free methods is present will the
clock interrupt and execute the events during the interval. So, if no free event is present the clock
behaves like the default clock, otherwise it behaves like the interrupt clock.
In a test using a fps of 30, a callback with a timeout of 0s, 0.001s, and 0.05s, resulted in a mean callback
delay of 0.00012s, 0.00017s, and 0.04121s seconds, respectively when it was a free event and 0.02403s,
0.02405s, and 0.04829s, respectively when it wasn’t.

193
Free Only Clock

The Free clock executes all events when a free event was scheduled. This results in normal events also
being execute in the middle of the interval when a free event is scheduled. For example, above, when a
free event was absent, a normal event with a 0.001s timeout was delayed for 0.02405s. However, if a free
event happened to be also scheduled, the normal event was only delayed 0.00014s, which may be
undesirable.

The Free only clock (free_only) solves it by only executing free events during the interval and normal events
are always executed like with the default clock. For example, in the presence of a free event, a normal
event with a timeout of 0.001s still had a delay of 0.02406. So this clock, treats free and normal events
independently, with normal events always being fps limited, but never the free events.

Summary

The kivy clock type to use can be set with the kivy_clock option the config. If KIVY_CLOCK is present in
the environment it overwrites the config selection. Its possible values are as follows:
• When kivy_clock is default, the normal clock, ClockBase, which limits callbacks to the maxfps
quantization - is used.
• When kivy_clock is interrupt, a interruptible clock, ClockBaseInterrupt, which doesn’t limit any
callbacks to the maxfps - is used. Callbacks will be executed at any time.
• When kivy_clock is free_all, a interruptible clock, ClockBaseFreeInterruptAll, which doesn’t limit
any callbacks to the maxfps in the presence of free events, but in their absence it limits events
to the fps quantization interval - is used.
• When kivy_clock is free_only, a interruptible clock, ClockBaseFreeInterruptAll, which treats free
and normal events independently; normal events are fps limited while free events are not - is
used.

20.7.9 Async clock support

New in version 2.0.0.

Experimental async support has been added in 2.0.0. The Clock now has a ClockBaseBehavior.
async_tick() and ClockBaseBehavior.async_idle() coroutine method which is used by the kivy
EventLoop when the kivy EventLoop is executed in a asynchronous manner. When used, the kivy
clock does not block while idling.
The async library to use is selected with the KIVY_EVENTLOOP environmental variable or by calling
init_async_lib() directly. The library can be one of “asyncio” when the standard library asyncio should
be used, or “trio” if the trio library should be used. If not set it defaults to “asyncio”.
See app for example usage.

kivy.clock.Clock: kivy.clock.ClockBase = None


The kivy Clock instance. See module documentation for details.

class kivy.clock.ClockBase(**kwargs)
Bases: kivy.clock.ClockBaseBehavior, kivy._clock.CyClockBase
The default kivy clock. See module for details.
usleep(microseconds)
Sleeps for the number of microseconds.

class kivy.clock.ClockBaseBehavior(async_lib='asyncio', **kwargs)


Bases: builtins.object

194
Traduit de Anglais vers Français - www.onlinedoctranslator.com

La base de l'horloge Kivy.


Paramètres

async_lib: chaîne de caractères La bibliothèque async à utiliser lorsque l'horloge est exécutée de manière asynchrone.

Peut être l'un des, "asyncio" quand la bibliothèque standard asyncio doit être utilisée, ou
"trio" si la bibliothèque trio doit être utilisée.

Il est par défaut 'asyncio' ou la valeur de la variable environnementale


KIVY_EVENTLOOP si défini. init_async_lib() peut également être appelé directement
pour définir la bibliothèque.

MIN_SOMMEIL = 0,005
Le temps minimum pour dormir. Si le temps restant est inférieur à cela, la boucle d'événements continuera.

async async_idle()
version asynchrone (interne) de inactif().

async async_tick()
version asynchrone de cocher().

cadres de propriété
Nombre d'images internes (pas nécessairement dessinées) depuis le début de l'horloge.

Nouveau dans la version 1.8.0.

propriété frames_displayed
Nombre d'images affichées depuis le début de l'horloge.

durée de la propriété
Temps passé entre la dernière image et l'image actuelle (en secondes).

Nouveau dans la version 1.8.0.

get_boottime()
Obtenez le temps en secondes depuis le démarrage de l'application.

get_fps()
Obtenez le FPS moyen actuel calculé par l'horloge.

get_rfps()
Obtenez le FPS "réel" actuel calculé par l'horloge. Ce compteur reflète la fréquence d'images
réelle affichée à l'écran.

Contrairement à get_fps(), cette fonction renvoie un compteur du nombre d'images, pas la moyenne
des images par seconde.

obtenir du temps()

Obtenez le dernier tick fait par l'horloge.

inactif()
(interne) attend ici jusqu'à la prochaine image.

init_async_lib(lib)
Définit manuellement la bibliothèque asynchrone à utiliser en interne, lors de l'exécution de manière asynchrone.

Cela peut être appelé à tout moment avant le début de la boucle d'événements kivy, mais pas une fois que l'application kivy est en cours

d'exécution.

Paramètres

lib: chaîne de caractères La bibliothèque async à utiliser lorsque l'horloge est exécutée de manière asynchrone. Pouvez

être l'un de, "asyncio" quand la bibliothèque standard asyncio doit être utilisée, ou "trio" si
la bibliothèque trio doit être utilisée.

195
post_idle(ts, courant)
Appelé après inactif() par cocher().

pre_idle()
Appelé avant inactif() par cocher().

cocher()
Avancez l'horloge à l'étape suivante. Doit être appelé à chaque trame. L'horloge par défaut a une fonction
tick() appelée par le framework Kivy de base.

tick_draw()
Cochez le compteur de dessins.

temps statique()
Méthode proxy pour horloge().

tu dors(microsecondes)
Dort pendant le nombre de microsecondes.

classer kivy.horloge.HorlogeBaseLibreInterruptionTous(**kwargs)
Bases : kivy.clock.ClockBaseInterruptFreeBehavior, kivy._clock.
CyClockBaseGratuit
le free_all horloge de Kivy. Voir module pour plus de détails.

classer kivy.horloge.ClockBaseFreeInterruptOnly(**kwargs)
Bases : kivy.clock.ClockBaseInterruptFreeBehavior, kivy._clock.
CyClockBaseGratuit
le gratuit_seulement horloge de Kivy. Voir module pour plus de détails.

async async_idle()
version asynchrone (interne) de inactif().

inactif()
(interne) attend ici jusqu'à la prochaine image.

classer kivy.horloge.HorlogeBaseInterruption(interupt_next_only=Faux, **kwargs)


Bases : kivy.clock.ClockBaseInterruptBehavior, kivy._clock.CyClockBase
le interrompre horloge de Kivy. Voir module pour plus de détails.

classer kivy.horloge.HorlogeBaseInterruptionComportement(interupt_next_only=Faux, **kwargs)


Bases : kivy.clock.ClockBaseBehavior
Une horloge Kivy qui peut être interrompue pendant une trame pour exécuter des événements.

async async_idle()
version asynchrone (interne) de inactif().

inactif()
(interne) attend ici jusqu'à la prochaine image.

init_async_lib(lib)
Définit manuellement la bibliothèque asynchrone à utiliser en interne, lors de l'exécution de manière asynchrone.

Cela peut être appelé à tout moment avant le début de la boucle d'événements kivy, mais pas une fois que l'application kivy est en cours

d'exécution.

Paramètres

lib: chaîne de caractères La bibliothèque async à utiliser lorsque l'horloge est exécutée de manière asynchrone. Pouvez

être l'un de, "asyncio" quand la bibliothèque standard asyncio doit être utilisée, ou "trio" si
la bibliothèque trio doit être utilisée.

tu dors(microsecondes)
Dort pendant le nombre de microsecondes.

196
classer kivy.horloge.HorlogeBaseInterruptionLibreComportement(**kwargs)
Bases : kivy.clock.ClockBaseInterruptBehavior
Une classe de base pour l'horloge qui interrompt l'intervalle de sommeil pour les événements gratuits.

classer kivy.horloge.HorlogeEvénement(Horloge CyClockBase, boucle int, rappeler, double délai d'attente, heure de démarrage double,
cid=Aucun, int trigger=Faux, clock_ended_callback=Aucun,
release_ref=Vrai, **kwargs)
Bases : Builtins.object
Cette classe n'est jamais créée par l'utilisateur ; à la place, kivy crée et renvoie une instance de cette classe lors de
la planification d'un rappel.

Un événement peut être déclenché (planifié) en l'appelant. Si c'est déjà programmé, rien ne se passera, sinon ce
sera programmé. Par exemple:

un événement = Horloge.horaire_une fois(mon_rappel, .5)


un événement() # rien ne se passera puisque c'est déjà programmé. un événement.
Annuler() # annule ça un événement() # maintenant c'est à nouveau programmé.

rappeler
rappel : objet
Annuler()
Annule le rappel s'il devait être appelé. S'il n'est pas programmé, rien ne se passe.
cid
cid : objet
horloge
horloge : kivy._clock.CyClockBase CyClockBase instance associée à l'événement.
clock_ended_callback
clock_ended_callback : objet Un rappel facultatif pour cet événement, qui, s'il est fourni, est appelé
par l'horloge

lorsque l'horloge est arrêtée et que l'événement n'a pas été coché.

get_callback()
Renvoie le rappel associé à l'événement. Les rappels sont stockés avec une référence indirecte afin de
ne pas garder les objets en vie. Si le rappel est mort, None est renvoyé.

get_clock_ended_callback()
Renvoie le clock_ended_callback associé à l'événement. Les rappels sont stockés avec une référence
indirecte afin de ne pas garder les objets en vie. Si le rappel est mort ou n'a pas été fourni, None est
renvoyé.

est déclenché
Renvoie si l'événement est programmé pour que son rappel soit exécuté par le thread kivy.

boucler

loop: 'int' Indique si cet événement se répète à des intervalles de temps libre.

suivant

suivant : kivy._clock.ClockEvent Le suivant HorlogeEvénement dans l'ordre où ils ont été programmés.

précédent

prev: kivy._clock.ClockEvent Le précédent HorlogeEvénement dans l'ordre où ils ont été programmés.

Libération()
(méthode interne) Convertit le rappel en une référence indirecte.

197
release_ref
release_ref : 'int' Si True, l'événement ne doit jamais libérer la référence aux rappels.

Si False, une référence faible peut être créée à la place.

cocher(double court)
(méthode interne) Traite l'événement pour le thread kivy.

temps libre
timeout : 'double' La durée après la planification lorsque le rappel doit être exécuté.

faible_rappel
faible_callback : objet

faible_horloge_ended_callback
low_clock_ended_callback : objet
exception kivy.horloge.ClockNotRunningError
Bases : Erreur d'exécution

Levée par l'Horloge Kivy lors de la programmation d'un événement si l'Horloge Kivy est déjà terminée (
stop_horloge a été appelé).

classer kivy.horloge.CyClockBase(**kwargs)
Bases : Builtins.object
résolution_horloge
résolution_horloge : 'double' Si le temps restant jusqu'à l'expiration de l'événement est inférieur à
résolution_horloge,
l'horloge exécutera le rappel même s'il n'a pas exactement expiré.

Si -1, la valeur par défaut, la résolution sera calculée à partir de la configuration maxfps. Sinon, la valeur
fournie est utilisée. La valeur par défaut est -1.

create_lifecycle_aware_trigger(rappeler, clock_ended_callback, délai d'attente=0, intervalle=Faux,


release_ref=Vrai) → HorlogeEvénement
Créez un événement déclencheur similaire à create_trigger(), mais l'événement est sensible à l'état de
l'horloge.

Si cet événement est déclenché après l'arrêt de l'horloge (stop_horloge()), puis un


ClockNotRunningError sera élevé. Si l'erreur n'est pas levée, alors soitrappeler ou
clock_ended_callback sera appelé. rappeler sera appelé lorsque l'événement est normalement
exécuté. Si l'horloge est arrêtée avant de pouvoir être exécutée, à condition que l'application se soit
fermée normalement sans plantage et que l'événement n'ait pas été annulé manuellement, et que les
rappels ne soient pas récupérés, alorsclock_ended_callback sera appelé à la place lorsque l'horloge
est arrêtée.

Paramètres

rappeler: appelable Le rappel à exécuter depuis kivy. Il faut un seul paramètre


- le temps de kivy actuellement écoulé.

clock_ended_callback: appelable Un rappel qui sera appelé si l'horloge est


arrêté alors que l'événement est encore programmé pour être appelé. Le rappel
prend un seul paramètre - l'objet événement. Lorsque l'événement est planifié avec
succès, si l'application s'est fermée normalement et que l'événement n'a pas été
annulé et que les rappels ne sont pas récupérés par la mémoire - il est garanti que
soitrappeler ou clock_ended_callback aurait été appelé.

temps libre: flotter Combien de temps attendre avant d'appeler le rappel.

intervalle: bool Si le rappel doit être appelé une fois (False) ou plusieurs fois
avec une période de temps libre (Vrai) comme schedule_interval().

198
release_ref : bobo Si Vrai, la défaut, ensuite si rappeler ou
clock_ended_callback est une méthode de classe et l'objet n'a aucune
référence à elle, alors l'objet peut être ramassé et les rappels ne seront pas
appelés. Si False, l'horloge conserve une référence à l'objet l'empêchant
d'être ramassée - elle sera donc appelée.
Retour UNE HorlogeEvénement exemple. Pour planifier le rappel de cette instance, vous pouvez
appeler.

Nouveau dans la version 2.0.0.

create_trigger(rappeler, délai d'attente=0, intervalle=Faux, release_ref=Vrai) → HorlogeEvénement


Créez un événement déclencheur. C'est thread-safe mais pas __del__ ou __dealloc__ sûr (voir
schedule_del_safe()). Consultez la documentation du module pour plus d'informations.

Pour annuler l'événement avant qu'il ne soit exécuté, appelez ClockEvent.cancel() sur l'événement retourné. Pour le
programmer à nouveau, appelez simplement l'événement (un événement()) et il sera reprogrammé en toute sécurité s'il
n'est pas déjà programmé.

Paramètres

rappeler: appelable Le rappel à exécuter depuis kivy. Il faut un seul paramètre


- le temps de kivy actuellement écoulé.

temps libre: flotter Combien de temps attendre avant d'appeler le rappel.

intervalle: bool Si le rappel doit être appelé une fois (False) ou plusieurs fois
avec une période de temps libre (Vrai) comme schedule_interval().

release_ref : bobo Si True, la valeur par défaut, alors si rappeler est une méthode de classe et
l'objet n'a aucune référence à lui, alors l'objet peut être récupéré et les
rappels ne seront pas appelés. Si False, l'horloge conserve une référence à
l'objet l'empêchant d'être ramassée - elle sera donc appelée.
Retour UNE HorlogeEvénement exemple. Pour planifier le rappel de cette instance, vous pouvez
appeler.

Nouveau dans la version 1.0.5.

Modifié dans la version 1.10.0 : intervalle a été ajouté.

Modifié dans la version 2.0.0 : release_ref a été ajouté.


get_before_frame_events()
Renvoie la liste des HorlogeEvénement instances qui sont programmées pour être appelées avant la prochaine
trame (-1 temps libre).

Nouveau dans la version 2.1.0.

obtenir_événements()
Renvoie la liste des HorlogeEvénement instances actuellement planifiées.

get_min_timeout()
Renvoie le temps restant depuis le début de l'image actuelle pour l'événement avec le plus petit délai
d'attente.

obtenir_résolution()
Renvoie la résolution minimale de l'horloge. C'est une fonction derésolution_horloge et
maxfps fourni à la config.
handle_exception(e)
Fournit une opportunité de gérer l'exception d'un événement.

Si vous le souhaitez, l'exception est gérée, sinon elle doit être déclenchée à nouveau. Par défaut, il est à nouveau
levé.

199
Paramètres e – L'exception à gérer.
Nouveau dans la version 2.0.0.

a fini
has_ended : 'int'

itération_max
max_iteration: 'int' Le nombre maximum d'itérations de rappel à la fin de la trame, avant la
suivante
Cadre. Si plusieurs itérations se produisent, un avertissement est émis.

on_planning(un événement)
Fonction qui est appelée en interne chaque fois qu'un événement est déclenché pour cette horloge. Il prend l'événement
comme paramètre.

L'ordre de on_planning les appels ne sont pas garantis d'être dans le même ordre que les événements sont
programmés. De même, il est possible que l'événement en cours de programmation ait été annulé avant que celui-
ci ne soit appelé sur l'événement. C'est parce queon_schedule() peut être appelé à partir de différents threads.

schedule_del_safe(rappeler)
Planifiez un rappel qui est thread-safe et __del__ ou __dealloc__ en sécurité.

Il n'est pas sûr d'appeler différents types de code à partir de __del__ ou __dealloc__ méthodes car elles
peuvent être exécutées à tout moment. La plupart des méthodes d'horloge de Kivy ne sont pas sûres pour
appeler l'horloge à partir de ces méthodes. Au lieu de cela, utilisez cette méthode, qui est thread-safe et __
del__ ou __dealloc__ safe, pour programmer le rappel dans le thread kivy. Il sera exécuté dans l'ordre après
le traitement des événements normaux.

Paramètres

rappeler: appelable Le rappel de l'exécution de kivy. Il ne prend aucun paramètre


et ne peut pas être annulé.

Nouveau dans la version 1.11.0.

horaire_intervalle(rappeler, temps libre) → HorlogeEvénement


Planifiez un événement à appeler toutes les <timeout> secondes. Voircreate_trigger() pour une
planification avancée et plus de détails.

Pour annuler l'événement avant qu'il ne soit exécuté, appelez ClockEvent.cancel() sur l'événement
retourné. Si le rappel est une méthode de classe, une référence faible à l'objet est créée et elle peut être
récupérée s'il n'y a pas d'autre référence à l'objet.

Retour UNE HorlogeEvénement exemple. Contrairement àcreate_trigger() qui seulement


crée l'événement déclencheur, cette méthode le planifie également.

schedule_lifecycle_aware_del_safe(rappeler, clock_ended_callback)
Planifiez un rappel qui est thread-safe et __del__ ou __dealloc__ sûr de la même manière que
schedule_del_safe(), mais le rappel est sensible à l'état de l'horloge.
Si cet événement est déclenché après l'arrêt de l'horloge (stop_horloge()), puis un
ClockNotRunningError sera élevé. Si l'erreur n'est pas levée, alors soitrappeler ou
clock_ended_callback sera appelé. rappeler sera appelé lorsque le rappel sera exécuté
normalement. Si l'horloge est arrêtée avant de pouvoir être exécutée, à condition que
l'application s'est fermée normalement sans planter, alorsclock_ended_callback sera appelé à la
place lorsque l'horloge est arrêtée.

Paramètres

rappeler: appelable Le rappel de l'exécution de kivy. Il ne prend aucun paramètre


et ne peut pas être annulé.

200
clock_ended_callback: appelable Un rappel qui sera appelé si l'horloge est
arrêté alors que le rappel est toujours programmé pour être appelé. Le rappel
prend un seul paramètre - le rappel. Si l'application s'est fermée normalement, il
est garanti que soitrappeler ou clock_ended_callback aurait été appelé.

Nouveau dans la version 2.0.0.

horaire_une fois(rappeler, délai d'attente=0) → HorlogeEvénement


Planifiez un événement en <timeout> secondes. Si <timeout> n'est pas spécifié ou est égal à 0, le rappel
sera appelé après le rendu de la prochaine image. Voircreate_trigger() pour une planification avancée et
plus de détails.

Pour annuler l'événement avant qu'il ne soit exécuté, appelez ClockEvent.cancel() sur l'événement
retourné. Si le rappel est une méthode de classe, une référence faible à l'objet est créée et elle peut être
récupérée s'il n'y a pas d'autre référence à l'objet.

Retour UNE HorlogeEvénement exemple. Contrairement àcreate_trigger() qui seulement


crée l'événement déclencheur, cette méthode le planifie également.

Modifié dans la version 1.0.5 : Si le timeout est de -1, le rappel sera appelé avant la prochaine trame (à
tick_draw()).

start_clock()
Doit être appelé pour démarrer l'horloge.

Une fois stop_horloge() est appelé, il ne peut pas être redémarré.

stop_horloge()
Arrête l'horloge et nettoie.
Cela doit être appelé pour traiter les rappels lifecycle_aware, etc.

imprévu(rappeler, tout=vrai)
Supprimer un événement précédemment programmé.

Une HorlogeEvénement peut également être annulé directement en appelant ClockEvent.cancel().

Paramètres

rappeler: HorlogeEvénement ou un appelable. Si c'est un HorlogeEvénement exemple, alors le


le rappel associé à cet événement sera annulé s'il est programmé.
S'il s'agit d'un appelable, alors l'appelable ne sera pas planifié s'il a été planifié.

Avertissement: Passer la fonction de rappel plutôt que le retour


HorlogeEvénement entraînera une déprogrammation beaucoup plus lente.

tout: bool Si vrai et si rappeler est un appelable, toutes les instances de cet appelable seront
non planifié (c'est-à-dire si cet appelable a été planifié plusieurs fois). Par défaut à Vrai
.

Modifié dans la version 1.9.0 : Le paramètre all a été ajouté. Avant, il se comportait comme sitout a été Vrai.

classer kivy.horloge.CyClockBaseGratuit
Bases : kivy._clock.CyClockBase
Une classe d'horloge qui prend en charge la planification d'événements gratuits en plus des événements normaux.

Chacun de create_trigger(), horaire_une fois(), et schedule_interval() Les méthodes, qui créent un


événement normal, ont une méthode correspondante pour créer un événement libre.

create_lifecycle_aware_trigger(rappeler, clock_ended_callback, délai d'attente=0, intervalle=Faux,


release_ref=Vrai) → FreeClockEvénement

201
create_lifecycle_aware_trigger_free(rappeler, clock_ended_callback, délai d'attente=0,
intervalle=Faux, release_ref=Vrai) →
FreeClockEvénement
Semblable à create_lifecycle_aware_trigger(), mais crée à la place un événement gratuit.

create_trigger(rappeler, délai d'attente=0, intervalle=Faux, release_ref=Vrai) → FreeClockEvénement

create_trigger_free(rappeler, délai d'attente=0, intervalle=Faux, release_ref=Vrai) → FreeClockEvénement


Semblable à create_trigger(), mais crée à la place un événement gratuit.

get_min_free_timeout()
Renvoie le temps restant depuis le début de l'image actuelle pour le gratuit événement avec le plus petit
délai d'attente.

horaire_intervalle(rappeler, temps libre) → FreeClockEvénement

schedule_interval_free(rappeler, temps libre) → FreeClockEvénement


Semblable à schedule_interval(), mais crée à la place un événement gratuit.

horaire_une fois(rappeler, délai d'attente=0) → FreeClockEvénement

horaire_une fois_gratuit(rappeler, délai d'attente=0) → FreeClockEvénement


Semblable à horaire_une fois(), mais crée à la place un événement gratuit.

classer kivy.horloge.FreeClockEvénement(gratuit, *grands, **kwargs)


Bases : kivy._clock.ClockEvent
CyClockBaseGratuit. Il stocke si l'événement a été planifié comme un événement gratuit.

gratuit
free : 'int' Indique si cet événement a été planifié comme un événement gratuit.

kivy.horloge.fil principal(fonction)
Décorateur qui planifiera l'appel de la fonction pour la prochaine trame disponible dans le thread principal. Cela peut être
utile lorsque vous utilisezUrlRequête ou lorsque vous programmez des threads : vous ne pouvez effectuer aucun travail
lié à OpenGL dans un thread.

Veuillez noter que cette méthode retournera directement et qu'aucun résultat ne pourra être retourné :

@mainthread
déf rappeler(soi, *arguments): imprimer(« La
demande a réussi ! »,
'Ce rappel est appelé dans le thread principal.')

soi.req = UrlRequête(URL='http://...', on_success=rappeler)

Nouveau dans la version 1.8.0.

20.8 Module de compatibilité pour Python 2.7 et >= 3.4

Ce module fournit un ensemble de types et de fonctions d'utilitaires pour l'optimisation et pour aider à l'écriture de code
compatible Python 2/3.

kivy.compat.PY2 = Faux
Faux, car nous ne prenons plus en charge Python 2.

kivy.compat.horloge() → flavoine
Une horloge avec la résolution la plus élevée disponible sur votre système d'exploitation actuel.

kivy.compat.est proche(une, b, *, rel_tol=1e-09, abs_tol=0.0)


Déterminez si deux nombres à virgule flottante sont proches en valeur.

202
rel_tol différence maximale pour être considérée comme « proche », par rapport à l'ampleur de
les valeurs d'entrée

abs_tol différence maximale pour être considéré comme « proche », quelle que soit l'ampleur
des valeurs d'entrée

Renvoie True si a est proche en valeur de b, et False sinon.

Pour que les valeurs soient considérées comme proches, la différence entre elles doit être inférieure à au moins
une des tolérances.

- inf, inf et NaN se comportent de manière similaire à la norme IEEE 754. C'est-à-dire que NaN n'est proche de rien, même
de lui-même. inf et -inf ne sont proches que d'eux-mêmes.

kivy.compat.string_types
alias de str

20.9 Objet de configuration

le Configuration object est une instance d'un Python ConfigParser modifié. Voir leDocumentation ConfigParser
pour plus d'informations.

Kivy a un fichier de configuration qui détermine les paramètres par défaut. Afin de modifier ces paramètres, vous pouvez
modifier ce fichier manuellement ou utiliser l'objet Config. S'il vous plaît voir leConfigurer Kivy rubrique pour plus
d'informations.

20.9.1 Application des configurations

Les options de configuration contrôlent l'initialisation du Application. Afin d'éviter les situations où les paramètres de
configuration ne fonctionnent pas ou ne sont pas appliqués avant la création de la fenêtre (comme la définition d'une
taille de fenêtre initiale), Config.set doit être utilisé avant d'importer d'autres modules Kivy. Idéalement, cela signifie les
définir dès le début de votre script main.py.

Alternativement, vous pouvez enregistrer ces paramètres de manière permanente en utilisant Config.set ensuite Config.écriture. Dans
ce cas, vous devrez redémarrer l'application pour que les modifications prennent effet. Notez que cette approche affectera toutes les
applications Kivy à l'échelle du système.

Veuillez noter qu'aucun trait de soulignement (_) sont autorisés dans le nom de la section.

20.9.2 Utilisation de l'objet Config

Pour lire un jeton de configuration à partir d'une section particulière :

> > > à partir de kivy.config importer Configuration


> > > Configuration.obtenir('kivy', 'Afficher fps') 0

Modifiez la configuration et enregistrez-la :

> > > Configuration.ensemble('post-proc', 'conserver_temps', '50')


> > > Configuration.écrivez()

Pour plus d'informations sur la configuration de votre Application, veuillez consulter le Paramétrage des applications section.

Modifié dans la version 1.7.1 : Le ConfigParser devrait maintenant fonctionner correctement avec utf-8. Les valeurs sont
converties d'ascii en unicode uniquement lorsque cela est nécessaire. La méthode get() renvoie des chaînes utf-8.

203
20.9.3 Modification de la configuration avec des variables d'environnement

Depuis la 1.11.0, il est désormais possible de modifier la configuration à l'aide de variables d'environnement. Ils sont
prioritaires sur le config.ini chargé. Le format est :

KCFG_<section>_<clé> = <valeur>

Par example:

KCFG_GRAPHICS_FULLSCREEN=auto . . . KCFG_KIVY_LOG_LEVEL=avertissement . . .
Ou dans votre dossier avant tout import kivy :

importer os os.environ["KCFG_KIVY_LOG_LEVEL"] = "avertissement"

Si vous ne souhaitez mapper aucune variable d'environnement, vous pouvez désactiver le comportement :

système d'exploitation.environ["KIVY_NO_ENV_CONFIG"] = "1"

20.9.4 Jetons de configuration disponibles

kivy
police par défaut: liste Polices par défaut utilisées pour les widgets affichant n'importe quel texte. Il dé-
défauts à ['Roboto', 'data/fonts/Roboto-Regular.ttf', 'data/fonts/Roboto-Italic.ttf',
'data/fonts/Roboto-Bold.ttf', 'data/fonts/Roboto- BoldItalic.ttf'].

bureau: entier, 0 ou 1 Cette option contrôle les fonctionnalités spécifiques du système d'exploitation de bureau, telles que l'activation

barre de défilement pouvant être déplacée dans les vues de défilement, désactivation des bulles dans TextInput, etc. 0 est

désactivé, 1 est activé.

exit_on_escape: entier, 0 ou 1 Permet de quitter Kivy lorsque l'échappement est enfoncé. 0 est désactivé,
1 est activé.
pause_on_minimize: entier, 0 ou 1 Si réglé sur 1, la boucle principale est interrompue et le on_pause
L'événement est distribué lorsque la fenêtre est réduite. Cette option est destinée à une utilisation sur le
bureau uniquement. Par défaut à0.

clavier: chaîne de caractères Identifiant de la mise en page à utiliser.

mode_clavier: chaîne de caractères Spécifie le mode clavier à utiliser. Si peut être l'un des
beuglant :

• '' - Laissez Kivy choisir la meilleure option pour votre plateforme actuelle.

• 'système' - vrai clavier.


• 'dock' - un clavier virtuel ancré sur un côté de l'écran.

• 'multi' - un clavier virtuel pour chaque requête de widget.

• 'systemanddock' - clavier connecté virtuel plus entrée du clavier réel.


• 'systemandmulti' - analogue.
kivy_clock: un des défaut, interrompre, free_all, gratuit_seulement Le type d'horloge à utiliser avec
kivy. Voirkivy.horloge.

log_dir: chaîne de caractères Chemin du répertoire des journaux.

log_enable: entier, 0 ou 1 Activez la journalisation des fichiers. 0 est désactivé, 1 est activé.

log_level: chaîne, l'un des 'trace', 'debug', 'info', 'warning', 'error' ou 'critical' Met le
niveau de journalisation minimum à utiliser.

nom_journal: chaîne de caractères Chaîne de format à utiliser pour le nom de fichier du fichier journal.

204
log_maxfiles: entier Conservez les fichiers journaux récents de log_maxfiles tout en purgeant le répertoire des journaux. Ensemble

'log_maxfiles' à -1 pour désactiver la purge des fichiers journaux (par exemple, conserver tous les fichiers journaux).

Noter: Vous vous retrouvez avec des fichiers journaux 'log_maxfiles + 1' car l'enregistreur en ajoute un
nouveau après la purge.

icône_fenêtre: chaîne de caractères Chemin de l'icône de la fenêtre. Utilisez-le si vous souhaitez remplacer le
icône pygame par défaut.

postproc

double_tap_distance: flotter Distance maximale autorisée pour un double tap, normalisé


dans la plage 0 - 1000.
double_tap_time: entier Temps autorisé pour la détection de double tap, en millisecondes.

ignorer: liste de tuples Liste des régions où les nouvelles touches sont ignorées. Cette configuration
Le jeton peut être utilisé pour résoudre les problèmes de hotspot avec du matériel DIY. Le format de la
liste doit être :

ignorer = [(xmin, ymin, xmax, ymax), ...]

Toutes les valeurs doivent être comprises dans la plage 0 - 1.

jitter_distance: entier Distance maximale pour la détection de gigue, normalisée à l'intérieur de la plage
0 - 1000.

jitter_ignore_devices: chaîne, séparée par des virgules Liste des appareils à ignorer
détection de gigue.

conserver_distance: entier Si le toucher se déplace plus que ce qui est indiqué par keep_distance, il
ne sera pas retenu. L'argument doit être un entier compris entre 0 et 1000.

retenir_temps: entier Temps autorisé pour une touche retenue, en millisecondes.

triple_tap_distance: flotter Distance maximale autorisée pour un triple tap,


côté la plage 0 - 1000.
triple_tap_time: entier Temps alloué pour la détection du triple tap, en millisecondes.

graphique

sans frontières: int, un de 0 ou 1 Si réglé sur 1, supprime la bordure/la décoration de la fenêtre. Gagner-
dow redimensionnement doit également être désactivé pour masquer la bordure de redimensionnement.

custom_titlebar: int, un de 0 ou 1 Si réglé sur 1, supprime la bordure de la fenêtre et permet


utilisateur pour définir un widget comme barre de titre voir set_custom_titlebar() pour une utilisation détaillée

custom_titlebar_border: entier, par défaut à 5 définit le nombre de pixels de la frontière


doit être utilisé comme cadre de rezising

état_fenêtre: chaîne , l'un des 'visible', 'caché', 'maximisé'


ou "minimisé"
Définit l'état de la fenêtre, par défaut sur « visible ». Cette option n'est disponible que pour le fournisseur de
fenêtres SDL2 et doit être utilisée sur les systèmes d'exploitation de bureau.

fbo: chaîne, l'un des 'hardware', 'software' ou 'force-hardware' Sélectionne le retour FBO-
fin à utiliser.

plein écran: int ou string, l'un des 0, 1, 'fake' ou 'auto' Activer le plein écran. Si réglé sur1, une
Resolution de largeur fois la taille pixels seront utilisés. Si réglé surauto, la résolution de votre
écran actuel sera utilisée à la place. C'est probablement ce que vous voulez. Si vous

205
voulez placer la fenêtre dans un autre affichage, utilisez faux, ou définissez le sans frontières option de
la section graphique, puis ajustez largeur, la taille, Haut et à gauche.

la taille: entier Hauteur de la Fenêtre, pas utilisé si plein écran est réglé sur auto.

à gauche: entier position gauche du Fenêtre.

maxfps: entier, par défaut à 60 FPS maximum autorisé.

Avertissement: La définition de maxfps sur 0 entraînera une utilisation maximale du processeur.

'multisamples' : int, par défaut à 2 Définit le Anti-aliasing multi-échantillons (MSAA) niveau.


L'augmentation de cette valeur permet d'obtenir des graphiques plus fluides, mais au détriment du temps de
traitement.

Noter: Cette fonctionnalité est limitée par la prise en charge matérielle du périphérique et n'aura aucun effet sur les
périphériques qui ne prennent pas en charge le niveau de MSAA demandé.

position: chaîne, l'un des 'auto' ou 'custom' Position de la fenêtre sur votre écran. Si
auto est utilisé, vous n'avez aucun contrôle sur la position initiale : Haut et à gauche sont ignorés.

show_cursor: int, un de 0 ou 1 Définissez si le curseur est affiché ou non sur la fenêtre.


Haut: entier La première place du Fenêtre.

redimensionnable: int, un de 0 ou 1 Si 0, la fenêtre aura une taille fixe. Si 1, la fenêtre


sera redimensionnable.

rotation: int, l'un des 0, 90, 180 ou 270 Rotation de la Fenêtre.

largeur: entier Largeur de la Fenêtre, pas utilisé si plein écran est réglé sur auto.

largeur_minimale: entier Largeur minimale à laquelle restreindre la fenêtre. (sdl2 uniquement)

hauteur_minimale: entier Hauteur minimale à laquelle restreindre la fenêtre. (sdl2 uniquement)

min_state_time: flottant, la valeur par défaut est .035 Temps minimum pour que les widgets affichent un
état visuel. Cet attribut est actuellement utilisé par des widgets commeMenu déroulant &
Comportement des boutons pour s'assurer qu'ils affichent leur état visuel actuel pour le temps
donné.

allow_screensaver: int, l'un de 0 ou 1, par défaut à 1 Autoriser l'appareil à afficher un écran


économiseur, ou d'aller dormir sur des appareils mobiles. Ne fonctionne que pour le fournisseur de fenêtres
sdl2.

vsync: rien, valeur vide ou entiers Si vsync est activé, actuellement uniquement utilisé
avec fenêtre sdl2. Les valeurs possibles sontrien ou valeur vide - la laisse inchangée, 0 -
désactive vsync, 1 ou plus grand - définit l'intervalle vsync, -1 définit la synchronisation
adaptative. Il retombe à 1 si le réglage est2+ ou -1 manqué. VoirSDL_GL_SetSwapInterval.

verify_gl_main_thread: int, 1 ou 0, par défaut à 1 S'il faut vérifier si le code qui change
toutes les instructions gl s'exécutent en dehors du thread principal, puis génèrent une erreur.

saisir Vous pouvez créer de nouveaux périphériques d'entrée en utilisant cette syntaxe :

# exemple d'instance de fournisseur d'entrée votre


identifiant = fournisseurid,paramètres

# exemple pour le fournisseur de


cours défaut= tuio,127.0.0.1:3333 tuio,
ma table = 192.168.0.1:3334

206
Voir également:

Vérifiez les fournisseurs dans kivy.input.fournisseurs pour la syntaxe à utiliser dans le fichier de
configuration.

widgets

scroll_distance: entier Valeur par défaut du scroll_distance propriété utilisée par le


ScrollView widget. Consultez la documentation du widget pour plus d'informations.

scroll_friction: flotter Valeur par défaut du scroll_friction propriété utilisée par le


ScrollView widget. Consultez la documentation du widget pour plus d'informations.

Obsolète depuis la version 1.7.0 : veuillez utiliser effect_cls plutôt.

scroll_timeout: entier Valeur par défaut du scroll_timeout propriété utilisée par le


ScrollView widget. Consultez la documentation du widget pour plus d'informations.

scroll_stoptime: entier Valeur par défaut du scroll_stoptime propriété utilisée par le


ScrollView widget. Consultez la documentation du widget pour plus d'informations.

Obsolète depuis la version 1.7.0 : veuillez utiliser effect_cls plutôt.

scroll_moves: entier Valeur par défaut du scroll_moves propriété utilisée par le


ScrollView widget. Consultez la documentation du widget pour plus d'informations.

Obsolète depuis la version 1.7.0 : veuillez utiliser effect_cls plutôt.

modules Vous pouvez activer des modules avec cette syntaxe :

nommodule =

Tout ce qui se trouve après le = sera transmis au module en tant qu'arguments. Consultez la documentation
du module spécifique pour une liste des arguments acceptés.

Modifié dans la version 2.1.0 : vsync a été ajouté à la section graphique. verify_gl_main_thread a été ajouté
à la section graphique.

Modifié dans la version 1.10.0 : min_state_time et allow_screensaver ont été ajoutés au graphique section.
kivy_clock a été ajouté à la section kivy. police par défaut a été ajouté à la section kivy.
Modifié dans la version 1.9.0 : sans frontières et état_fenêtre ont été ajoutés à la section graphique. lefaux
réglage de la plein écran l'option a été dépréciée, utilisez le sans frontières option à la place. pause_on_minimize
a été ajouté à la section kivy.

Modifié dans la version 1.8.0 : systemanddock et systemandmulti a été ajoutée comme valeurs possibles pour
mode_clavier dans la section Kivy. exit_on_escape a été ajouté à la section kivy.

Modifié dans la version 1.2.0 : redimensionnable a été ajouté à la section graphique.

Modifié dans la version 1.1.0 : tuio n'écoute plus par défaut. Les icônes de fenêtre ne sont plus copiées dans le répertoire utilisateur. Vous
pouvez toujours définir une nouvelle icône de fenêtre en utilisant leicône_fenêtre paramètre de configuration.

Modifié dans la version 1.0.8 : scroll_timeout, scroll_distance et scroll_friction ont été ajoutés.
list_friction, list_trigger_distance et list_friction_bound ont été supprimés. type_clavier et clavier ont
été supprimés du widget. mode_clavier et clavier ont été ajoutés à la section kivy.

kivy.config.Configuration = Aucune
L'objet de configuration Kivy par défaut. C'est unConfigParser exemple avec le Nom réglé sur
« kivy ».

Configuration = ConfigParser(Nom='kivy')

classer kivy.config.ConfigParser(nom='', **kwargs)


Bases : configparser.RawConfigParser, builtins.object

207
Classe ConfigParser améliorée qui prend en charge l'ajout de sections et de valeurs par défaut.

Par défaut, l'instance kivy ConfigParser, Configuration, est appelé 'kivy' et l'instance ConfigParser utilisée
par le App.build_settings la méthode est nommée 'application'.

Paramètres

Nom: chaîne de caractères Le nom de l'instance. VoirNom. Par défaut à''.

Modifié dans la version 1.9.0 : chaque ConfigParser peut désormais être nommé. Vous pouvez obtenir le
ConfigParser associé à un nom en utilisantget_configparser(). De plus, vous pouvez maintenant contrôler les
valeurs de configuration avecConfigParserProperty.

Nouveau dans la version 1.0.7.

ajouter_rappel(rappeler, section=Aucun, clé=Aucun)


Ajoutez un rappel à appeler lorsqu'une section ou une touche spécifique a changé. Si vous ne spécifiez pas de
section ou de clé, il appellera le rappel pour tous les changements de section/clé.

Les rappels recevront 3 arguments : la section, la clé et la valeur.

Nouveau dans la version 1.4.1.

ajouter une section par défaut(section)


Ajoutez une section si la section est manquante.

avoir(section, option, **kwargs)


Obtenez une valeur d'option pour une section donnée.

Si v̀ars' est fourni, il doit s'agir d'un dictionnaire. L'option est recherchée dans v̀ars' (si elle est fournie),
section', et dans D̀EFAULTSECT' dans cet ordre. Si la clé n'est pas trouvée et`fallback' est fourni, il est
utilisé comme valeur de secours. « un » peut être fourni en tant que`valeur de repli.

Si l'interpolation est activée et l'argument optionnel `raw' est False, toutes les interpolations sont
développées dans les valeurs de retour.

Arguments bruts', `vars', et `fallback' sont des mots clés uniquement.

La section DEFAULT est spéciale.

get_configparser statique(Nom)
Renvoie le ConfigParser instance dont le nom est Nom, ou Aucun s'il n'est pas trouvé.

Paramètres

Nom: chaîne de caractères Le nom du ConfigParser exemple à retourner.

obtenir par défaut(section, option, valeur par défaut)


Obtenez la valeur d'une option dans la section spécifiée. S'il n'est pas trouvé, il renverra la valeur par défaut.

getdefaultint(section, option, valeur par défaut)


Obtenez la valeur d'une option dans la section spécifiée. S'il n'est pas trouvé, il renverra la valeur par défaut.
La valeur sera toujours renvoyée sous forme d'entier.

Nouveau dans la version 1.6.0.

nom de la propriété
Le nom associé à cette instance ConfigParser, sinon ''. Par défaut à''. Il peut être modifié en toute sécurité de
manière dynamique ou défini sur''.

Lorsqu'un ConfigParser reçoit un nom, cet objet de configuration peut être récupéré en utilisant
get_configparser(). De plus, cette instance de configuration peut également être utilisée avec un
ConfigParserProperty instance qui a défini son configuration valeur à ce nom.

Définir plus d'un ConfigParser avec le même nom augmentera Erreur de valeur.

208
lire(nom de fichier)
Lire un seul nom de fichier. Contrairement au ConfigParser original de Python, celui-ci est capable de
lire un seul fichier à la fois. Le dernier fichier lu sera utilisé pour leécrivez() méthode.

Modifié dans la version 1.9.0 : lire() appelle maintenant les rappels si read a changé des valeurs.

remove_callback(rappeler, section=Aucun, clé=Aucun)


Supprime un rappel ajouté avec add_callback(). remove_callback() doit être appelé avec
les mêmes paramètres que add_callback().
Élève un Erreur de valeur s'il n'est pas trouvé.

Nouveau dans la version 1.9.0.

ensemble(section, option, valeur)


Fonctionne de manière similaire à la méthode set de PythonConfigParser, sauf que la valeur est implicitement
convertie en chaîne.

mettre tous(section, valeurs-clés)


Définit plusieurs paires clé-valeur dans une section. keyvalues doit être un dictionnaire contenant les
paires clé-valeur à définir.

définir par defaut(section, option, valeur)


Définissez la valeur par défaut pour une option dans la section spécifiée.

définir les valeurs par défaut(section, valeurs-clés)

Définissez plusieurs valeurs-clés par défaut dans une section. keyvalues doit être un dictionnaire contenant les
nouvelles valeurs par défaut.

mise à jour_config(nom de fichier, écraser=Faux)


Mettez à niveau la configuration en fonction d'un nouveau fichier de configuration par défaut. Écrasez toutes les valeurs existantes si
overwrite est True.

écrivez()
Écrivez la configuration dans le dernier fichier ouvert à l'aide de la lire() méthode.

Renvoie True si l'écriture s'est terminée avec succès, False sinon.

20.10 Contexte

Nouveau dans la version 1.8.0.

Avertissement: Ceci est expérimental et sujet à changement tant que cet avertissement est présent.

Kivy a quelques instances « globales » qui sont utilisées directement par de nombreux éléments du framework : Cacher, Constructeur, Horloge.

A FAIRE : documenter ce module.

classer kivy.context.Le contexte(init=Faux)


Bases : Builtins.dict
pop(k[, ré ]) → v, supprime la clé spécifiée et renvoie la valeur correspondante.
Si la clé n'est pas trouvée, d est retourné si donné, sinon KeyError est levée

kivy.context.get_current_context()
Renvoie le contexte actuel.

kivy.context.registre_contexte(Nom, cls, *arguments, **kwargs)


Enregistrez un nouveau contexte.

209
20.11 Répartiteur d'événements

Tous les objets qui produisent des événements dans Kivy implémentent le Répartiteur d'événements qui fournit une interface cohérente pour
l'enregistrement et la manipulation des gestionnaires d'événements.

Modifié dans la version 1.0.9 : la découverte de propriétés et les méthodes ont été déplacées de la Widget à la
Répartiteur d'événements.

classer kivy.événement.Répartiteur d'événements(**kwargs)


Bases : kivy.event.ObjectWithUid
Voir la docstring du module pour l'utilisation.

appliquer_propriété(**kwargs)
Ajoute des propriétés au moment de l'exécution à la classe. La fonction accepte les arguments mot-
clé de la formeprop_name=prop, où soutenir est un Propriété exemple et prop_name est le nom de
l'attribut de la propriété.

Nouveau dans la version 1.9.1.

Avertissement: Cette méthode n'est pas recommandée pour un usage courant car vous devez déclarer
les propriétés dans votre classe au lieu d'utiliser cette méthode.

Par example:

>>> imprimer(largeur.propriété('des bâtons', calmer=Vrai))


Rien
> > > largeur.appliquer_propriété(des bâtons=Propriété de l'objet(55, max=dix))
calmer=Vrai))
> > > imprimer(largeur.propriété('des bâtons',
<objet Kivy.properties.ObjectProperty à 0x04303130>

lier(**kwargs)
Liez un type d'événement ou une propriété à un rappel.

Usage:

# Avec Propriétés
déf my_x_callback(obj, valeur):
imprimer('sur objet', obj, 'x changé en', valeur)
déf my_width_callback(obj, valeur):
imprimer('sur objet', obj, 'largeur changée en', valeur) soi.lier(X=
my_x_callback, largeur=my_width_callback)

# Avec un événement
déf my_press_callback(obj): imprimer(
'événement sur objet', obj) soi.lier(on_press=
my_press_callback)

En général, les rappels de propriété sont appelés avec 2 arguments (l'objet et la nouvelle valeur de la
propriété) et les rappels d'événement avec un argument (l'objet). L'exemple ci-dessus illustre cela.

L'exemple suivant montre différentes manières d'utiliser la fonction bind dans une application
complète :

à partir de kivy.uix.boxlayout importer BoxLayout à partir


de kivy.app importer Application
(suite à la page suivante)

210
(suite de la page précédente)

à partir de bouton kivy.uix importer Bouton à partir


de outils fonctionnels importer partiel

classer DemoBox(BoxLayout):
"""
Cette classe démontre diverses techniques qui peuvent être utilisées
??
→ pour lier à
événements. Bien que les pièces puissent être rendues plus optimales, avancées
??
→ Concepts Python
sont évités pour des raisons de lisibilité et de clarté. """

déf __init__(soi, super( * *kwargs):


DemoBox, soi. soi).__init__(**kwargs)
orientation = "verticale"

# Nous commençons par lier à un événement normal. Le seul


??
→ argument
# passé au callback est l'objet que nous avons lié
??
→ à.
btn = Bouton(texte=« Liaison normale à l'événement ») btn.
lier(on_press=soi.on_event)

# Ensuite, nous nous lions à un événement de changement de propriété standard. Cette


??
→ typiquement
# passe 2 arguments : l'objet et la valeur
btn2 = Bouton(texte=« Liaison normale à un changement de propriété »)
btn2.lier(Etat=soi.sur_propriété)

# Ici, nous utilisons des fonctions anonymes (aka lambdas) pour


??
→ effectuer la liaison.
# Leur avantage est que vous pouvez éviter de déclarer de nouveaux
→ fonctions,
?? c'est-à-dire
# ils offrent un moyen concis de " rediriger " les rappels. btn3 =
Bouton(texte="Utiliser des fonctions anonymes.") btn3.lier(on_press
=lambda X: soi.on_event(Rien))

# Vous pouvez également déclarer une fonction qui accepte une variable de
??
→ numéro
# arguments positionnels et mots-clés et utiliser l'introspection
??
→ à déterminer
# ce qui est transmis. C'est très pratique pour
→ débogage aussi
??

# comme fonction de réutilisation. Ici, nous utilisons la liaison d'événements standard


??
→ à une fonction
# qui accepte les arguments de position et de mot-clé facultatifs. btn4 =
Bouton(texte="Utiliser une fonction flexible") btn4.lier(on_press=soi.
sur_n'importe quoi)

# Enfin, nous montrons comment utiliser les fonctions partielles. Ils sont
??
→ parfois
# difficile à saisir, mais offre une
??
→ moyen puissant de
(suite à la page suivante)

211
(suite de la page précédente)

# fonctions de réutilisation.
btn5 = Bouton(texte="En utilisant des fonctions partielles. Pour les inconditionnels.
??
→ ")
btn5.lier(on_press=partiel(soi.sur_n'importe quoi, "1", "2",
??
→ mensuel="python"))

pour mais dans [btn, btn2, btn3, btn4, btn5] :


soi.add_widget(mais)

déf on_event(soi, obj):


imprimer("Événement typique de", obj)

déf sur_propriété(soi, obj, valeur):


imprimer("Changement de propriété typique de", obj, "à", valeur)

déf sur_n'importe quoi(soi, *arguments, **kwargs):


imprimer('La fonction flexible a *args of', str(arguments),
"et **kwargs de", str(kwargs))

classer DemoApp(Application):
déf construire(soi):
retourner DemoBox()

si __Nom__ == "__principale__":
DemoApp().Cours()

Si un rappel a déjà été lié à un événement ou à une propriété donnée, il ne sera plus ajouté.

Lors de la liaison d'une méthode à un événement ou à une propriété, un kivy.weakmethod.WeakMethod


du rappel est enregistré. Autrement dit, plutôt que de stocker une référence régulière, il stocke à la fois une
référence faible à l'instance (voir Pythonfaible réf).

Cela a deux conséquences.

La première est que la liaison n'empêchera pas le ramasse-miettes de l'objet de la méthode. Le client
doit conserver une référence à l'instance pour la durée de vie souhaitée. La référence de rappel est
supprimée en silence si elle devient invalide.

La seconde est que lorsque vous utilisez une méthode décorée, par exemple :

@mon_décorateur
déf rappeler(soi, passe * arguments):

le décorateur (mon_décorateur ici) doit utiliser enveloppements intérieurement.

créer_propriété(nom unicode, valeur=Aucun, valeur_défaut=Vrai, *grands, **kwargs)


Créez une nouvelle propriété au moment de l'exécution.

Nouveau dans la version 1.0.9.

Modifié dans la version 1.8.0 : valeur paramètre ajouté, peut être utilisé pour définir la valeur par défaut de
la propriété. De plus, le type de la valeur est utilisé pour spécialiser la propriété créée.

Modifié dans la version 1.9.0 : dans le passé, si valeur était du type bobo, une Propriété numérique serait créé,
maintenant un Propriété booléenne est créé.

De plus, les arguments now et positionnels et les mots-clés sont transmis à la propriété lors de sa création.

212
Modifié dans la version 2.0.0 : default_value a été ajouté.

Avertissement: Cette fonction est conçue pour le langage Kivy, ne l'utilisez pas dans votre code. Vous
devez déclarer la propriété dans votre classe au lieu d'utiliser cette méthode.

Paramètres

Nom: chaîne de caractères Nom de la propriété

valeur: objet, facultatif Valeur par défaut de la propriété. Le type est également utilisé pour la création
types de propriété plus appropriés. La valeur par défaut est Aucun.

valeur par défaut: bool, True par défaut Si vrai, valeur sera la valeur par défaut pour le
propriété. Sinon, la propriété sera initialisée avec la valeur par défaut
normale du type de propriété, puis définie survaleur.

>>> monwidget = Widget()


>>> monwidget.créer_propriété('Douane')
>>> monwidget.Douane = Vrai
>>> imprimer(monwidget.Douane)
Vrai

envoi(type d'événement, *grands, **kwargs)


Distribuez un événement à tous les gestionnaires ajoutés dans bind/fbind(). Dès qu'un gestionnaire renvoie
True, la répartition s'arrête.

La fonction collecte tous les arguments de position et de mot-clé et les transmet aux
gestionnaires.

Noter: Les gestionnaires sont appelés dans l'ordre inverse de celui avec lequel ils ont été enregistrés lier().

Paramètres

type d'événement: str le nom de l'événement à distribuer.

Modifié dans la version 1.9.0 : la collecte et le transfert d'arguments de mots-clés ont été ajoutés.
Auparavant, seuls les arguments positionnels étaient collectés et transmis.

dispatch_children(type d'événement, *grands, **kwargs)

dispatch_generic(type d'événement, *grands, **kwargs)

événements()
Retourne tous les événements de la classe. Peut être utilisé pour l'introspection.

Nouveau dans la version 1.8.0.

fbind(Nom, fonction, *grands, **kwargs)


Une méthode de reliure avancée et généralement plus rapide. Cette méthode est différente delier()
et est destiné aux utilisateurs plus avancés et à un usage interne. Il peut être utilisé à condition de
respecter les points suivants.

1. Par opposition à lier(), il ne vérifie pas que cette fonction et largs/kwargs n'ont pas été liés
auparavant à ce nom. Donc, lier le même rappel plusieurs fois ne fera que continuer à
l'ajouter.

2. Bien que lier() crée un Méthode faible du rappel lors de la liaison à un événement ou à une propriété,
cette méthode stocke le rappel directement, à moins qu'un argument de mot-clé réf avec

213
la valeur True est fournie, puis un Méthode faible est enregistré. Ceci est utile lorsqu'il n'y a pas de
risque de fuite de mémoire en stockant directement le rappel.

3. Cette méthode renvoie un nombre positif unique si Nom a été trouvé et lié, et 0, autrement.
Il ne soulève pas d'exception, commelier() si la propriété Nom n'est pas trouvé. Si ce n'est
pas zéro, l'uid renvoyé est unique à ceNom et rappel et peut être utilisé avec unbind_uid()
pour délier.

Lors de la liaison d'un rappel avec largs et/ou kwargs, funbind() doit être utilisé pour la déliaison. Si
aucun largs et kwargs n'est fourni,délier() peut également être utilisé. unbind_uid() peut être utilisé
dans les deux cas.

This method passes on any caught positional and/or keyword arguments to the callback,
removing the need to call partial. When calling the callback the expended largs are passed on
followed by instance/value (just instance for kwargs) followed by expended kwargs.

Following is an example of usage similar to the example in bind():

class DemoBox(BoxLayout):

def __init__(self, super( * *kwargs):


DemoBox, self. self).__init__(**kwargs)
orientation = "vertical"

btn = Button(text="Normal binding to event") btn.fbind(


'on_press', self.on_event)

btn2 = Button(text="Normal binding to a property change") btn2.fbind('state'


, self.on_property)

btn3 = Button(text="A: Using function with args.") btn3.fbind('on_press', self


.on_event_with_args, 'right',
tree='birch', food='apple')

btn4 = Button(text="Unbind A.")


btn4.fbind('on_press', self.unbind_a, btn3)

btn5 = Button(text="Use a flexible function") btn5.fbind(


'on_press', self.on_anything)

btn6 = Button(text="B: Using flexible functions with args. hardcores.")



→ For
btn6.fbind('on_press', self.on_anything, "1", "2", monthy=

→ "python")

btn7 = Button(text="Force dispatch B with different params



→ ")
btn7.fbind('on_press', btn6.dispatch, 'on_press', 6, 7,

→ monthy="other python")

for but in [btn, btn2, btn3, btn4, btn5, btn6, btn7]:


self.add_widget(but)

def on_event(self, obj):


print("Typical event from", obj)

def on_event_with_args(self, side, obj, tree=None, food=None):


(continues on next page)

214
(continued from previous page)

print("Event with args", obj, side, tree, food)

def on_property(self, obj, value):


print("Typical property change from", obj, "to", value)

def on_anything(self, *args, **kwargs):


print('The flexible function has *args of', str(args),
"and **kwargs of", str(kwargs)) return
True

def unbind_a(self, btn, event):


btn.funbind('on_press', self.on_event_with_args, 'right',
tree='birch', food='apple')

Note: Since the kv lang uses this method to bind, one has to implement this method, instead of
bind() when creating a non EventDispatcher based class used with the kv lang. See
Observable for an example.

New in version 1.9.0.

Changed in version 1.9.1: The ref keyword argument has been added.

funbind(name, func, *largs, **kwargs)


Similar to fbind().
When unbinding, unbind() will unbind all callbacks that match the callback, while this
method will only unbind the first.
To unbind, the same positional and keyword arguments passed to fbind() must be passed on to
funbind.

Note: It is safe to use funbind() to unbind a function bound with bind() as long as no
keyword and positional arguments are provided to funbind().

New in version 1.9.0.

get_property_observers(name, args=False)
Returns a list of methods that are bound to the property/event passed as the name argument:

widget_instance.get_property_observers('on_release')

Parameters

name: str The name of the event or property.


args: bool Whether to return the bound args. To keep compatibility, only the
callback functions and not their provided args will be returned in the list when args is
False.

If True, each element in the list is a 5-tuple of (callback, largs, kwargs, is_ref, uid),
where is_ref indicates whether callback is a weakref, and uid is the uid given by
fbind(), or None if bind() was used. Defaults to False.
Returns The list of bound callbacks. See args for details.

New in version 1.8.0.

215
Changed in version 1.9.0: args has been added.

getter(name)
Return the getter of a property.

New in version 1.0.9.

is_event_type(event_type)
Return True if the event_type is already registered.

New in version 1.0.4.

properties() → dict
Return all the properties in the class in a dictionary of key/property class. Can be used for
introspection.

New in version 1.0.9.

property(name, quiet=False)
Get a property instance from the property name. If quiet is True, None is returned instead of
raising an exception when name is not a property. Defaults to False.

New in version 1.0.9.

Returns A Property derived instance corresponding to the name.

Changed in version 1.9.0: quiet was added.

proxy_ref
Returns a WeakProxy reference to the EventDispatcher.
New in version 1.9.0.

Changed in version 2.0.0: Previously it just returned itself, now it actually returns a
WeakProxy.
register_event_type(event_type)
Register an event type with the dispatcher.

Registering event types allows the dispatcher to validate event handler names as they are
attached and to search attached objects for suitable handlers. Each event type declaration must:

1. start with the prefix on_.

2. have a default handler in the class.

Example of creating a custom event:

class MyWidget(Widget):
def __init__(self, super( * *kwargs):
MyWidget, self).__init__(**kwargs)
self.register_event_type('on_swipe')

def on_swipe(self): pass

def on_swipe_callback(*largs): print('my swipe is


called', largs) MyWidget()
w=
w.dispatch('on_swipe')

setter(name)
Return the setter of a property. Use: instance.setter(‘name’). The setter is a convenient callback
function useful if you want to directly bind one property to another. It returns a partial

216
function that will accept (obj, value) args and results in the property ‘name’ of instance being set
to value.

New in version 1.0.9.

For example, to bind number2 to number1 in python you would do:

class ExampleWidget(Widget):
number1 = NumericProperty(None)
number2 = NumericProperty(None)

def __init__(self, **kwargs):


super(ExampleWidget, self).__init__(**kwargs) self.bind(
number1=self.setter('number2'))

This is equivalent to kv binding:

<ExampleWidget>:
number2: self.number1

unbind(**kwargs)
Unbind properties from callback functions with similar usage as bind().

If a callback has been bound to a given event or property multiple times, only the first
occurrence will be unbound.

Note: It is safe to use unbind() on a function bound with fbind() as long as that function
was originally bound without any keyword and positional arguments. Otherwise, the
function will fail to be unbound and you should use funbind() instead.

unbind_uid(name, uid)
Uses the uid returned by fbind() to unbind the callback.
This method is much more efficient than funbind(). If uid evaluates to False (e.g. 0) a
ValueError is raised. Also, only callbacks bound with fbind() can be unbound with this
method.
Since each call to fbind() will generate a unique uid, only one callback will be removed. If uid is
not found among the callbacks, no error is raised.

E.g.:

btn6 = Button(text="B: Using flexible functions with args. For


→ hardcores.")

uid = btn6.fbind('on_press', self.on_anything, "1", "2", monthy=


→ "python")

if not uid:
raise Exception('Binding failed').
...
btn6.unbind_uid('on_press', uid)

New in version 1.9.0.

unregister_event_type(event_type)
Unregister an event type in the dispatcher.

Changed in version 2.1.0: Method renamed from unregister_event_types to


unregister_event_type.
unregister_event_types(self, event_type)

217
class kivy.event.ObjectWithUid
Bases: builtins.object
(internal) This class assists in providing unique identifiers for class instances. It is not intended for
direct usage.

class kivy.event.Observable
Bases: kivy.event.ObjectWithUid
Observable is a stub class defining the methods required for binding. EventDispatcher is (the)
one example of a class that implements the binding interface. See EventDispatcher for details.

New in version 1.9.0.

bind(**kwargs)
fbind(name, func, *largs, **kwargs)
See EventDispatcher.fbind().

Note: To keep backward compatibility with derived classes which may have inherited from
Observable before, the fbind() method was added. The default implementation of fbind()
is to create a partial function that it passes to bind while saving the uid and largs/kwargs.
However, funbind() (and unbind_uid()) are fairly inefficient since we have to first lookup
this partial function using the largs/kwargs or uid and then call unbind() on the returned
function. It is recommended to overwrite these methods in derived classes to bind directly
for better performance.
Similarly to EventDispatcher.fbind(), this method returns 0 on failure and a positive
unique uid on success. This uid can be used with unbind_uid().

funbind(name, func, *largs, **kwargs)


See fbind() and EventDispatcher.funbind().
unbind(**kwargs)
unbind_uid(name, uid)
See fbind() and EventDispatcher.unbind_uid().

20.12 Factory object

The factory can be used to automatically register any class or module and instantiate classes from it
anywhere in your project. It is an implementation of the Factory Pattern.

The class list and available modules are automatically generated by setup.py.

Example for registering a class/module:

> > > from kivy.factory import Factory


>>> Factory.register('Widget', Factory. module='kivy.uix.widget') module
>>> register('Vector', ='kivy.vector')

Example of using the Factory:

> > > from kivy.factory import Factory


> > > widget = Factory.Widget(pos=(456,456))
> > > vector = Factory.Vector(9, 2)

Example using a class name:

218
> > > from kivy.factory import Factory
> > > Factory.register('MyWidget', cls=MyWidget)

By default, the first classname you register via the factory is permanent. If you wish to change the
registered class, you need to unregister the classname before you re-assign it:

> > > from kivy.factory import Factory


> > > Factory.register('MyWidget', cls=MyWidget)
> > > widget = Factory.MyWidget()
>>> Factory.unregister('MyWidget')
>>> Factory.register('MyWidget', cls=CustomWidget)
> > > customWidget = Factory.MyWidget()

kivy.factory.Factory: kivy.factory.FactoryBase = <kivy.factory.FactoryBase object>

Factory instance to use for getting new classes

exception kivy.factory.FactoryException
Bases: Exception

20.13 Geometry utilities

This module contains some helper functions for geometric calculations.

kivy.geometry.circumcircle(a, b, c)
Computes the circumcircle of a triangle defined by a, b, c. See: http://en.wikipedia.org/wiki/
Circumscribed_circle
Parameters

a: iterable containing at least 2 values (for x and y) The 1st point of the triangle.

b: iterable containing at least 2 values (for x and y) The 2nd point of the triangle.
c: iterable containing at least 2 values (for x and y) The 3rd point of the triangle.
Return

A tuple that defines the circle :

• The first element in the returned tuple is the center as (x, y)

• The second is the radius (float)


kivy.geometry.minimum_bounding_circle(points)
Returns the minimum bounding circle for a set of points.

For a description of the problem being solved, see the Smallest Circle Problem.

The function uses Applet’s Algorithm, the runtime is O(h^3, *n), where h is the number of points
in the convex hull of the set of points. But it runs in linear time in almost all real world cases.
See: http://tinyurl.com/6e4n5yb
Parameters

points: iterable A list of points (2 tuple with x,y coordinates)


Return

A tuple that defines the circle:

• The first element in the returned tuple is the center (x, y)

• The second the radius (float)

219
20.14 Gesture recognition

This class allows you to easily create new gestures and compare them:

from kivy.gesture import Gesture, GestureDatabase

# Create a gesture g =
Gesture()
g.add_stroke(point_list=[(1,1), g.normalize (3,4), (2,1)])
()

# Add it to the database gdb =


GestureDatabase() gdb.
add_gesture(g)

# And for the next gesture, try to find it! g2 = Gesture()

#...
gdb.find(g2)

Warning: You don’t really want to do this: it’s more of an example of how to construct gestures
dynamically. Typically, you would need a lot more points, so it’s better to record gestures in a file and
reload them to compare later. Look in the examples/gestures directory for an example of how to do
that.

class kivy.gesture.Gesture(tolerance=None)
Bases: builtins.object
A python implementation of a gesture recognition algorithm by Oleg Dopertchouk: http://www.
gamedev.net/reference/articles/article2039.asp

Implemented by Jeiel Aranal (chemikhazi@gmail.com), released into the public domain.

add_stroke(point_list=None)
Adds a stroke to the gesture and returns the Stroke instance. Optional point_list argument is a
list of the mouse points for the stroke.

dot_product(comparison_gesture)
Calculates the dot product of the gesture with another gesture.

get_rigid_rotation(dstpts)
Extract the rotation to apply to a group of points to minimize the distance to a second group of
points. The two groups of points are assumed to be centered. This is a simple version that just
picks an angle based on the first point of the gesture.

get_score(comparison_gesture, rotation_invariant=True)
Returns the matching score of the gesture against another gesture.

normalize(stroke_samples=32)
Runs the gesture normalization algorithm and calculates the dot product with self.

class kivy.gesture.GestureDatabase
Bases: builtins.object
Class to handle a gesture database.

add_gesture(gesture)
Add a new gesture to the database.

220
find(gesture, minscore=0.9, rotation_invariant=True)
Find a matching gesture in the database.

gesture_to_str(gesture)
Convert a gesture into a unique string.

str_to_gesture(data)
Convert a unique string to a gesture.

class kivy.gesture.GestureStroke
Bases: builtins.object
Gestures can be made up of multiple strokes.

add_point(x=x_pos, y=y_pos)
Adds a point to the stroke.

center_stroke(offset_x, offset_y)
Centers the stroke by offsetting the points.

normalize_stroke(sample_points=32)
Normalizes strokes so that every stroke has a standard number of points. Returns True if stroke
is normalized, False if it can’t be normalized. sample_points controls the resolution of the stroke.

points_distance(point1=GesturePoint, point2=GesturePoint)
Returns the distance between two GesturePoints.

scale_stroke(scale_factor=float)
Scales the stroke down by scale_factor.

stroke_length(point_list=None)
Finds the length of the stroke. If a point list is given, finds the length of that list.

20.15 Interactive launcher

New in version 1.3.0.

Deprecated since version 1.10.0: The interactive launcher has been deprecated.

The InteractiveLauncher provides a user-friendly python shell interface to an App so that it can be
prototyped and debugged interactively.

Note: The Kivy API intends for some functions to only be run once or before the main EventLoop has
started. Methods that can normally be called during the course of an application will work as intended, but
specifically overriding methods such as on_touch() dynamically leads to trouble.

20.15.1 Creating an InteractiveLauncher

Take your existing subclass of App (this can be production code) and pass an instance to the
InteractiveLauncher constructor.

from kivy.interactive import InteractiveLauncher from kivy.app


import App
from kivy.uix.button import Button

class MyApp(App):
(continues on next page)

221
(continued from previous page)

def build(self):
return Button(text='Hello Shell')

launcher = InteractiveLauncher(MyApp()) launcher.


run()

After pressing enter, the script will return. This allows the interpreter to continue running. Inspection or
modification of the App can be done safely through the InteractiveLauncher instance or the provided
SafeMembrane class instances.

Note: If you want to test this example, start Python without any file to have already an interpreter, and
copy/paste all the lines. You’ll still have the interpreter at the end + the kivy application running.

20.15.2 Interactive Development

IPython provides a fast way to learn the Kivy API. The App instance and all of its attributes, including
methods and the entire widget tree, can be quickly listed by using the ‘.’ operator and pressing ‘tab’. Try
this code in an Ipython shell.

from kivy.interactive import InteractiveLauncher from kivy.app


import App
from kivy.uix.widget import Widget from
kivy.graphics import Color, Ellipse

class MyPaintWidget(Widget):
def on_touch_down(self, with touch):
self.canvas:
Color(1, 1, 0) d =
30.
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))

class TestApp(App):
def build(self):
return Widget()

i = InteractiveLauncher(TestApp()) i.run()

i. # press 'tab' to list attributes of the app


i.root. # press 'tab' to list attributes of the root widget

# App is boring. Attach a new widget! i.root.


add_widget(MyPaintWidget())

i.safeIn()
# The application is now blocked.
# Click on the screen several times. i.safeOut()

# The clicks will show up now

(continues on next page)

222
(continued from previous page)

# Erase artwork and start over i.root.


canvas.clear()

Note: All of the proxies used in the module store their referent in the _ref attribute, which can be
accessed directly if needed, such as for getting doc strings. help() and type() will access the proxy, not
its referent.

20.15.3 Directly Pausing the Application

Both the InteractiveLauncher and SafeMembrane hold internal references to the EventLoop’s ‘safe’
and ‘confirmed’ threading.Event objects. You can use their safing methods to control the application
manually.
SafeMembrane.safeIn() will cause the application to pause and SafeMembrane.safeOut() will allow
a paused application to continue running. This is potentially useful for scripting actions into functions
that need the screen to update etc.

Note: The pausing is implemented via the Clocks' schedule_once() method and occurs before the
start of each frame.

20.15.4 Adding Attributes Dynamically

Note: This module uses threading and object proxies to encapsulate the running App. Deadlocks and
memory corruption can occur if making direct references inside the thread without going through the
provided proxy(s).

The InteractiveLauncher can have attributes added to it exactly like a normal object and if these were
created from outside the membrane, they will not be threadsafe because the external references to them
in the python interpreter do not go through InteractiveLauncher’s membrane behavior, inherited from
SafeMembrane.
To threadsafe these external references, simply assign them to SafeMembrane instances of themselves like so:

from kivy.interactive import SafeMembrane

interactiveLauncher.attribute = myNewObject
# myNewObject is unsafe
myNewObject = SafeMembrane(myNewObject)
# myNewObject is now safe. Call at will.
myNewObject.method()

223
TODO

Unit tests, examples, and a better explanation of which methods are safe in a running application would be
nice. All three would be excellent.

Could be re-written with a context-manager style i.e.

with safe:
foo()

Any use cases besides compacting code?

class kivy.interactive.InteractiveLauncher(app=None, *args, **kwargs)


Bases: kivy.interactive.SafeMembrane
Proxy to an application instance that launches it in a thread and then returns and acts as a proxy to
the application in the thread.

class kivy.interactive.SafeMembrane(ob, *args, **kwargs)


Bases: builtins.object
This help is for a proxy object. Did you want help on the proxy’s referent instead? Try using
help(<instance>._ref)
The SafeMembrane is a threadsafe proxy that also returns attributes as new thread-safe objects and
makes thread-safe method calls, preventing thread-unsafe objects from leaking into the user’s
environment.

safeIn()
Provides a thread-safe entry point for interactive launching.

safeOut()
Provides a thread-safe exit point for interactive launching.

20.16 Kivy Base

This module contains the Kivy core functionality and is not intended for end users. Feel free to look
through it, but bare in mind that calling any of these methods directly may result in an unpredictable
behavior as the calls access directly the event loop of an application.

kivy.base.EventLoop = <kivy.base.EventLoopBase object>


EventLoop instance

class kivy.base.EventLoopBase
Bases: kivy.event.EventDispatcher
Main event loop. This loop handles the updating of input and dispatching events.

add_event_listener(listener)
Add a new event listener for getting touch events.

add_input_provider(provider, auto_remove=False)
Add a new input provider to listen for touch events.

add_postproc_module(mod)
Add a postproc input module (DoubleTap, TripleTap, DeJitter RetainTouch are defaults).

async async_idle()
Identical to idle(), but instead used when running within an async event loop.
close()
Exit from the main loop and stop all configured input providers.

224
dispatch_input()
Called by EventLoopBase.idle() to read events from input providers, pass events to
postproc, and dispatch final events.
ensure_window()
Ensure that we have a window.

exit()
Close the main loop and close the window.

idle()
This function is called after every frame. By default:

• it “ticks” the clock to the next frame.


• it reads all input and dispatches events.

• it dispatches on_update, on_draw and on_flip events to the window.

on_pause()
Event handler for on_pause which will be fired when the event loop is paused.

on_start()
Event handler for on_start which will be fired right after all input providers have been started.

on_stop()
Event handler for on_stop events which will be fired right after all input providers have been
stopped.

post_dispatch_input(etype, me)
This function is called by EventLoopBase.dispatch_input() when we want to dispatch an
input event. The event is dispatched to all listeners and if grabbed, it’s dispatched to
grabbed widgets.
remove_android_splash(*args)
Remove android presplash in SDL2 bootstrap.

remove_event_listener(listener)
Remove an event listener from the list.

remove_input_provider(provider)
Remove an input provider.

Changed in version 2.1.0: Provider will be also removed if it exist in auto-remove list.

remove_postproc_module(mod)
Remove a postproc module.

run()
Main loop

set_window(window)
Set the window used for the event loop.

start()
Must be called before EventLoopBase.run(). This starts all configured input providers.
Changed in version 2.1.0: Method can be called multiple times, but event loop will start only
once.

stop()
Stop all input providers and call callbacks registered using EventLoop.add_stop_callback().

Changed in version 2.1.0: Method can be called multiple times, but event loop will stop only
once.

225
property touches
Return the list of all touches currently in down or move states.

class kivy.base.ExceptionHandler
Bases: builtins.object
Base handler that catches exceptions in runTouchApp(). You can subclass and extend it as follows:

class E(ExceptionHandler):
def handle_exception(self, inst):
Logger.exception('Exception caught by ExceptionHandler') return
ExceptionManager.PASS

ExceptionManager.add_handler(E())

Then, all exceptions will be set to PASS, and logged to the console!

handle_exception(exception)
Called by ExceptionManagerBase to handle a exception.
Defaults to returning ExceptionManager.RAISE that re-raises the exception. Return
ExceptionManager.PASS to indicate that the exception was handled and should be ignored.

This may be called multiple times with the same exception, if ExceptionManager.RAISE is
returned as the exception bubbles through multiple kivy exception handling levels.

kivy.base.ExceptionManager: kivy.base.ExceptionManagerBase =
<kivy.base.ExceptionManagerBase object>
The ExceptionManagerBase instance that handles kivy exceptions.

class kivy.base.ExceptionManagerBase
Bases: builtins.object
ExceptionManager manages exceptions handlers.

PASS = 1
The exception should be ignored as it was handled by the handler.

RAISE = 0
The exception should be re-raised.

add_handler(cls)
Add a new exception handler to the stack.

handle_exception(inst)
Called when an exception occurred in the runTouchApp() main loop.

remove_handler(cls)
Remove the exception handler from the stack.

async kivy.base.async_runTouchApp(widget=None, embedded=False, async_lib=None)


Identical to runTouchApp() but instead it is a coroutine that can be run in an existing async
event loop.
async_lib is the async library to use. See kivy.app for details and example usage.
New in version 2.0.0.

kivy.base.runTouchApp(widget=None, embedded=False)
Static main function that starts the application loop. You can access some magic via the following
arguments:

See kivy.app for example usage.

226
Parameters

<empty> To make dispatching work, you need at least one input listener. If not,
application will leave. (MTWindow act as an input listener)

widget If you pass only a widget, a MTWindow will be created and your widget
will be added to the window as the root widget.

embedded No event dispatching is done. This will be your job.


widget + embedded No event dispatching is done. This will be your job but we try
to get the window (must be created by you beforehand) and add the widget to
it. Very useful for embedding Kivy in another toolkit. (like Qt, check
kivydesigned)
kivy.base.stopTouchApp()
Stop the current application by leaving the main loop.

See kivy.app for example usage.

20.17 Logger object

The Kivy Logger class provides a singleton logger instance. This instance exposes a standard Python logger
object but adds some convenient features.

All the standard logging levels are available : trace, debug, info, warning, error and critical.

20.17.1 Example Usage

Use the Logger as you would a standard Python logger.

from kivy.logger import Logger

Logger.info('title: This is a info message.') Logger.debug('title:


This is a debug message.')

try:
raise Exception('bleh') except
Exception:
Logger.exception('Something happened!')

The message passed to the logger is split into two parts separated by a colon (:). The first part is used as a
title and the second part is used as the message. This way, you can “categorize” your messages easily.

Logger.info('Application: This is a test')

# will appear as

[INFO ] [Application ] This is a test

You can change the logging level at any time using the setLevel method.

from kivy.logger import Logger, LOG_LEVELS

Logger.setLevel(LOG_LEVELS["debug"])

227
20.17.2 Features

Although you are free to use standard python loggers, the Kivy Logger offers some solid benefits and
useful features. These include:

• simplied usage (single instance, simple configuration, works by default)

• color-coded output
• output to stdout by default

• message categorization via colon separation

• access to log history even if logging is disabled

• built-in handling of various cross-platform considerations

Kivys’ logger was designed to be used with kivy apps and makes logging from Kivy apps more convenient.

20.17.3 Logger Configuration

The Logger can be controlled via the Kivy configuration file:

[kivy]
log_level = info
log_enable = 1
log_dir = logs
log_name = kivy_%y-%m-%d_%_.txt
log_maxfiles = 100

More information about the allowed values are described in the kivy.config module.

20.17.4 Logger History

Even if the logger is not enabled, you still have access to the last 100 messages:

from kivy.logger import LoggerHistory

print(LoggerHistory.history)

kivy.logger.Logger = <Logger kivy (WARNING)>


Kivy default logger instance

class kivy.logger.LoggerHistory(level=0)
Bases: logging.Handler
emit(message)
Do whatever it takes to actually log the specified logging record.

This version is intended to be implemented by subclasses and so raises a NotImplemented-


Error.

flush()
Ensure all logging output has been flushed.

This version does nothing and is intended to be implemented by subclasses.

228
20.18 Low level Metrics

Module for low level metrics operations.

kivy._metrics.dispatch_pixel_scale(*args)
Dispatches all properties that and watch pixel_scale_observers.

This should be called by Metrics when it changes any of the scaling properties.

kivy._metrics.dpi2px(value, unicode ext) → float


Converts the value according to the ext.

kivy._metrics.sync_pixel_scale(dpi=None, density=None, fontscale=None)


Internal method to manually updated the scaling factors when metrics changes, before anything has
been dispatched.

Do not call in user code!

20.19 Metrics

New in version 1.5.0.

A screen is defined by its physical size, density and resolution. These factors are essential for creating UI’s
with correct size everywhere.

In Kivy, all the graphics pipelines work with pixels. But using pixels as a measurement unit is problematic
because sizes change according to the screen.

20.19.1 Dimensions

If you want to design your UI for different screen sizes, you will want better measurement units to work
with. Kivy provides some more scalable alternatives.

Units

pt Points - 1/72 of an inch based on the physical size of the screen. Prefer to use sp
instead of pt.

mm Millimeters - Based on the physical size of the screen.


cm Centimeters - Based on the physical size of the screen.
in Inches - Based on the physical size of the screen.
dp Density-independent Pixels - An abstract unit that is based on the physical density
of the screen. With a density of 1, 1dp is equal to 1px. When running on a higher
density screen, the number of pixels used to draw 1dp is scaled up a factor
appropriate to the screen’s dpi, and the inverse for a lower dpi. The ratio of dp-
topixels will change with the screen density, but not necessarily in direct proportion.
Using the dp unit is a simple solution to making the view dimensions in your layout
resize properly for different screen densities. In others words, it provides consistency
for the real-world size of your UI across different devices.

sp Scale-independent Pixels - This is like the dp unit, but it is also scaled by the user’s
font size preference. We recommend you use this unit when specifying font sizes, so
the font size will be adjusted to both the screen density and the user’s preference.

229
20.19.2 Examples

Here is an example of creating a label with a sp font_size and setting the height manually with a 10dp
margin:

# :kivy 1.5.0
<MyWidget>:
Label:
text: 'Hello world'
font_size: '15sp'
size_hint_y: None
height: self.texture_size[1] + dp(10)

20.19.3 Manual control of metrics

The metrics cannot be changed at runtime. Once a value has been converted to pixels, you can’t retrieve
the original value anymore. This stems from the fact that the DPI and density of a device cannot be
changed at runtime.

We provide some environment variables to control metrics:

• KIVY_METRICS_DENSITY: if set, this value will be used for density instead of the systems one. On
android, the value varies between 0.75, 1, 1.5 and 2.

• KIVY_METRICS_FONTSCALE: if set, this value will be used for fontscale instead of the systems
one. On android, the value varies between 0.8 and 1.2.
• KIVY_DPI: if set, this value will be used for dpi. Please note that setting the DPI will not impact the dp/
sp notation because these are based on the screen density.

For example, if you want to simulate a high-density screen (like the HTC One X):

KIVY_DPI=320 KIVY_METRICS_DENSITY=2 python main.py --size 1280x720

Or a medium-density (like Motorola Droid 2):

KIVY_DPI=240 KIVY_METRICS_DENSITY=1.5 python main.py --size 854x480

You can also simulate an alternative user preference for fontscale as follows:

KIVY_METRICS_FONTSCALE=1.2 python main.py

kivy.metrics.Metrics: kivy.metrics.MetricsBase = <kivy.metrics.MetricsBase object>

The metrics object storing the window scaling factors.

New in version 1.7.0.

Changed in version 2.1.0: Metrics is now a Context registered variable (like e.g. Clock).
class kivy.metrics.MetricsBase(**kwargs)
Bases: kivy.event.EventDispatcher
Class that contains the default attributes for Metrics. Don’t use this class directly, but use the Metrics
instance.

cm: float
The scaling factor that converts from centimeters to pixels.

230
cm is a AliasProperty containing the factor. E.g in KV: width: self.
texture_size[0] + 10 * Metrics.cm will update width when cm changes from a screen
configuration change.
density: float
The density of the screen.

This value is 1 by default on desktops but varies on android depending on the screen.

density is a AliasProperty and can be set to change the value. But, the density is reloaded
and reset if we got it from the Window and the Window density changed.
dp: float
The scaling factor that converts from density-independent pixels to pixels.

dp is a AliasProperty containing the factor. E.g in KV: width: self. texture_size[0] + 10 *


Metrics.dp will update width when dp changes from a screen configuration change.

dpi: float
The DPI of the screen.

Depending on the platform, the DPI can be taken from the Window provider (Desktop
mainly) or from a platform-specific module (like android/ios).
dpi is a AliasProperty and can be set to change the value. But, the density is reloaded and
reset if we got it from the Window and the Window dpi changed.
dpi_rounded: int
Return the dpi of the screen, rounded to the nearest of 120, 160, 240 or 320.

dpi_rounded is a AliasProperty and updates when dpi changes.


fontscale: float
The fontscale user preference.

This value is 1 by default but can vary between 0.8 and 1.2.

fontscale is a AliasProperty and can be set to change the value.


inch: float
The scaling factor that converts from inches to pixels.

inch is a AliasProperty containing the factor. E.g in KV: width: self.


texture_size[0] + 10 * Metrics.inch will update width when inch changes from a screen
configuration change.
mm: float
The scaling factor that converts from millimeters to pixels.

mm is a AliasProperty containing the factor. E.g in KV: width: self.


texture_size[0] + 10 * Metrics.mm will update width when mm changes from a screen
configuration change.
pt: float
The scaling factor that converts from points to pixels.

pt is a AliasProperty containing the factor. E.g in KV: width: self.


texture_size[0] + 10 * Metrics.pt will update width when pt changes from a screen
configuration change.
reset_dpi(*args)
Resets the dpi (and possibly density) to the platform values, overwriting any manually set
values.

231
reset_metrics()
Resets the dpi/density/fontscale to the platform values, overwriting any manually set
values.
sp: float
The scaling factor that converts from scale-independent pixels to pixels.

sp is a AliasProperty containing the factor. E.g in KV: width: self. texture_size[0] + 10 *


Metrics.sp will update width when sp changes from a screen configuration change.

kivy.metrics.cm(value) → float
Convert from centimeters to pixels

kivy.metrics.dp(value) → float
Convert from density-independent pixels to pixels

kivy.metrics.dpi2px(value, unicode ext) → float


Converts the value according to the ext.

kivy.metrics.inch(value) → float
Convert from inches to pixels

kivy.metrics.mm(value) → float
Convert from millimeters to pixels

kivy.metrics.pt(value) → float
Convert from points to pixels

kivy.metrics.sp(value) → float
Convert from scale-independent pixels to pixels

20.20 Multistroke gesture recognizer

New in version 1.9.0.

Warning: This is experimental and subject to change as long as this warning notice is present.

See kivy/examples/demo/multistroke/main.py for a complete application example.

20.20.1 Conceptual Overview

This module implements the Protractor gesture recognition algorithm.

Recognizer is the search/database API similar to GestureDatabase. It maintains a list of


MultistrokeGesture objects and allows you to search for a user-input gestures among them.
ProgressTracker tracks the progress of a Recognizer.recognize() call. It can be used to interact with
the running recognizer task, for example forcing it to stop half-way, or analyzing results as they
arrive.
MultistrokeGesture represents a gesture in the gesture database (Recognizer.db). It is a container
for UnistrokeTemplate objects, and implements the heap permute algorithm to automatically
generate all possible stroke orders (if desired).
UnistrokeTemplate represents a single stroke path. It’s typically instantiated automatically by
MultistrokeGesture, but sometimes you may need to create them manually.

232
Candidate represents a user-input gesture that is used to search the gesture database for matches. It is
normally instantiated automatically by calling Recognizer.recognize().

20.20.2 Usage examples

See kivy/examples/demo/multistroke/main.py for a complete application example.


You can bind to events on Recognizer to track the state of all calls to Recognizer.recognize(). The
callback function will receive an instance of ProgressTracker that can be used to analyze and control
various aspects of the recognition process

from kivy.vector import Vector from


kivy.multistroke import Recognizer

gdb = Recognizer()

def search_start(gdb, pt):


print("A search is starting with %d tasks" % (pt.tasks))

def search_stop(gdb, pt):


# This will call max() on the result dictionary, so it's best to store
# it instead of calling it 3 times consecutively best = pt.best

print("Search ended (%s). Best is %s (score %f, distance %f)" % (


pt.status, best['name'], best['score'], best['dist'] ))

# Bind your callbacks to track all matching operations gdb.bind(


on_search_start=search_start) gdb.bind(on_search_complete=
search_stop)

# The format below is referred to as `strokes`, a list of stroke paths.


# Note that each path shown here consists of two points, ie a straight
# line; if you plot them it looks like a T, hence the name. gdb.add_gesture('T'
,[
[Vector(30, 7), Vector(103, 7)], [Vector(66, 7),
Vector(66, 87)]])

# Now you can search for the 'T' gesture using similar data (user input).
# This will trigger both of the callbacks bound above. gdb.recognize([

[Vector(45, 8), Vector(110, 12)], [Vector(88, 9


), Vector(85, 95)]])

On the next Clock tick, the matching process starts (and, in this case, completes).

To track individual calls to Recognizer.recognize(), use the return value (also a ProgressTracker
instance)

# Same as above, but keep track of progress using returned value progress = gdb.
recognize([
[Vector(45, 8), Vector(110, 12)], [Vector(88, 9
), Vector(85, 95)]])

progress.bind(on_progress=my_other_callback) print(
progress.progress) # = 0
(continues on next page)

233
(continued from previous page)

# [ assuming a kivy.clock.Clock.tick() here ]

print(result.progress) # = 1

20.20.3 Algorithm details

For more information about the matching algorithm, see:

“Protractor: A fast and accurate gesture recognizer” by Yang Li http://yangl.org/pdf/


protractor-chi2010.pdf

“$N-Protractor” by Lisa Anthony and Jacob O. Wobbrock http://depts.washington.edu/aimgroup/


proj/dollar/ndollar-protractor.pdf
Some of the code is derived from the JavaScript implementation here: http://depts.washington.
edu/aimgroup/proj/dollar/ndollar.html
class kivy.multistroke.Candidate(strokes=None, numpoints=16, **kwargs)
Bases: builtins.object
Represents a set of unistroke paths of user input, ie data to be matched against a
UnistrokeTemplate object using the Protractor algorithm. By default, data is precomputed to
match both rotation bounded and fully invariant UnistrokeTemplate objects.
Arguments

strokes See MultistrokeGesture.strokes for format example. The Candi-


date strokes are simply combined to a unistroke in the order given. The idea is
that this will match one of the unistroke permutations in
MultistrokeGesture.templates.
numpoints The Candidate’s default N; this is only for a fallback, it is not normally
used since n is driven by the UnistrokeTemplate we are being compared to.

skip_bounded If True, do not generate/store rotation bounded vectors


skip_invariant If True, do not generate/store rotation invariant vectors
Note that you WILL get errors if you set a skip-flag and then attempt to retrieve the data.

add_stroke(stroke)
Add a stroke to the candidate; this will invalidate all previously computed vectors

get_angle_similarity(tpl, **kwargs)
(Internal use only) Compute the angle similarity between this Candidate and a
UnistrokeTemplate object. Returns a number that represents the angle similarity (lower is
more similar).
get_protractor_vector(numpoints, orientation_sens)
(Internal use only) Return vector for comparing to a UnistrokeTemplate with Protractor

get_start_unit_vector(numpoints, orientation_sens)
(Internal use only) Get the start vector for this Candidate, with the path resampled to numpoints
points. This is the first step in the matching process. It is compared to a UnistrokeTemplate
object’s start vector to determine angle similarity.

prepare(numpoints=None)
Prepare the Candidate vectors. self.strokes is combined to a single unistroke (connected endto-
end), resampled to numpoints points, and then the vectors are calculated and stored in self.db
(for use by get_distance and get_angle_similarity)

234

Vous aimerez peut-être aussi