Salutations! Aujourd'hui, nous parlerons à nouveau de la bibliothèque
KivyMD - un ensemble de widgets pour le développement multiplateforme en Python dans le style de Material Design. Dans cet article, je ne passerai pas en revue les widgets KivyMD, comme dans un
article récent , mais il s'agira plutôt de positionner les widgets. Quelque chose comme un tutoriel sur le développement d'applications mobiles en Python pour les débutants ne sera pas là, donc si vous entendez parler du framework Kivy pour la première fois, il est peu probable que vous soyez intéressé par tout cela. Eh bien, nous avons roulé sous la coupe!
L'autre jour, j'ai téléchargé l'application de démonstration Flutter UIKit depuis Google Play:
Et maintenant, nous allons essayer de répéter un écran de cette application. Regardons tout de suite les résultats: Flutter à gauche, Kivy & KivyMD à droite.
Certains éléments de l'interface utilisateur sont différents, non pas en raison de certaines caractéristiques techniques, à cause desquelles il était impossible d'obtenir un résultat identique, mais je pensais juste que ce serait plus organique (par exemple, la barre d'outils noire, à mon avis, ne semble pas du tout).
Alors! Qu'est-ce qui frappe quand on regarde l'écran que l'on va jouer? Disposition avant de fond transparent. Dans Kivy, cette fonctionnalité est fournie par FloatLayout, qui vous permet de placer des widgets et des contrôles les uns dans les autres comme suit:
Schématiquement, notre écran ressemblera à ceci:
La disposition de cet écran est assez simple:
Pourquoi est-ce que je parle de FloatLayout si notre écran est hérité de Screen?
<ProductScreen@Screen>: ...
Tout simplement parce que Screen -> RelativeLayout -> FloatLayout.
Tous les widgets de FloatLayout sont positionnés à partir du coin inférieur gauche, c'est-à-dire qu'à l'écran, ils se voient automatiquement attribuer la position (0, 0). Dans le balisage, il n'est pas difficile de tracer l'ordre d'ajout d'éléments à l'écran de haut en bas:
Si quelqu'un a fait attention, nous avons indiqué la position à un seul widget:
MDToolbar: ... pos_hint: {"top": 1}
En plus des coordonnées spécifiques (x, y), chaque widget dans Kivy peut recevoir un indice de position:
pos_hint: {"top": 1}
Donc, l'image de fond en bas ...
BoxLayout: size_hint_y: None height: root.height - toolbar.height FitImage: source: "smokestackheather.jpeg"
... grâce au widget FitImage (bibliothèque KivyMD), il est automatiquement étiré sur tout l'espace qui lui est alloué tout en conservant les proportions de l'image:
Par défaut, chaque widget et disposition dans Kivy reçoit 100% de l'espace, sauf indication contraire. Par exemple, si vous souhaitez ajouter un bouton à l'écran, vous allez évidemment procéder comme suit:
from kivy.app import App from kivy.lang import Builder KV = """ Button: text: "Button" """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run()
Et obtenez le résultat:
Le bouton occupait 100% de l'espace. Pour placer un bouton au centre de l'écran, vous devez, d'une part, lui donner la taille requise et, d'autre part, indiquer où il sera situé:
from kivy.app import App from kivy.lang import Builder KV = """ Button: text: "Button" size_hint: None, None size: 100, 50 pos_hint: {"center_y": .5, "center_x": .5} """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run()
Maintenant, l'image a changé:
Vous pouvez également spécifier la propriété
size_hint , de 0 à 1, (équivalant à 0-100%), c'est-à-dire l'indice de taille:
from kivy.app import App from kivy.lang import Builder KV = """ BoxLayout: Button: text: "Button" size_hint_y: .2 Button: text: "Button" size_hint_y: .1 Button: text: "Button" """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run()
Ou la même chose, mais l'indice de largeur (
size_hint_x ):
from kivy.app import App from kivy.lang import Builder KV = """ BoxLayout: Button: text: "Button" size_hint_x: .2 Button: text: "Button" size_hint_x: .1 Button: text: "Button" """ class MyApp(App): def build(self): return Builder.load_string(KV) MyApp().run()
MDToolbar a une hauteur de 56dp, ne peut pas occuper tout l'espace, et si vous ne lui dites pas que sa place est en haut, il collera automatiquement au bas de l'écran:
La liste des cartes - OrderProductLayout (nous en parlerons ci-dessous) - est une ScrollView avec des éléments MDCard et elle occupe toute la hauteur de l'écran, mais grâce au rembourrage (valeurs de retrait en bas), il semble qu'elle soit située légèrement au-dessus du centre de l'écran. Eh bien, par défaut, MDBottomAppBar jette l'ancre sur la bordure inférieure de l'écran. Par conséquent, seul MDToolbar nous a indiqué où sa place.
Voyons maintenant ce qu'est le widget OrderProductLayout:
Comme vous pouvez le voir, ce sont quatre cartes intégrées dans ScrillView. Contrairement à l'écran parent, hérité de FloatLayout, ici tous les widgets sont lus de haut en bas.
Ceci est très pratique, car il existe une hiérarchie claire de widgets, une structure arborescente et en un coup d'œil, il est clair quel widget / contrôle appartient à quelle disposition. Dans Kivy, la disposition la plus couramment utilisée est BoxLayout - une boîte qui vous permet de placer des widgets à l'intérieur de vous verticalement ou horizontalement (par défaut - le dernier):
Cela peut être vu plus clairement sur le diagramme suivant, où l'orientation horizontale de BoxLayout est utilisée:
Nous avons interdit à BoxLayout d'utiliser 100% de l'espace -
size_hint_y: None et dit - votre hauteur sera exactement la même que la hauteur de l'élément le plus haut imbriqué en vous -
height: self.minimum_height .
Liste d'images:
Si nous voulions utiliser le défilement vertical de la liste, nous aurions besoin de changer le GridLayout comme suit:
ScrollView: GridLayout: size_hint_y: None height: self.minimum_height cols: 1
Remplacez les lignes (colonnes) par des colonnes (
cols ) et indiquez au
minimum non pas la largeur, mais la hauteur:
from kivy.app import App from kivy.lang import Builder from kivy.metrics import dp from kivy.uix.button import Button KV = """ ScrollView: GridLayout: id: box size_hint_y: None height: self.minimum_height spacing: "5dp" cols: 1 """ class MyApp(App): def build(self): return Builder.load_string(KV) def on_start(self): for i in range(20): self.root.ids.box.add_widget( Button( text=f"Label {i}", size_hint_y=None, height=dp(40), ) ) MyApp().run()
Les cartes suivantes sont le choix de la couleur et de la taille (elles sont presque identiques):
Une caractéristique distinctive du langage de balisage Kv Language est non seulement la structure claire des widgets, mais aussi le fait que ce langage prend en charge certaines fonctionnalités du langage Python. A savoir: appeler des méthodes, créer / changer des variables, des opérations logiques, d'E / S et mathématiques ...
Calcul de la
valeur déclarée dans
Label ...
Label: value: 0 text: str(self.value)
... se produit directement dans le balisage lui-même:
MDIconButton: on_release: label_value.value -= 1 if label_value.value > 0 else 0
Et je ne croirai jamais que ce (code Flutter) ...
... plus logique et lisible que le code Kv Language:
Hier, on m'a demandé comment Kivy s'en sort avec l'environnement de développement. Existe-t-il des compléments automatiques, des chargements à chaud et d'autres équipements? Avec les compléments automatiques, tout va bien si vous utilisez PyCharm:
Quant au hotload ... Python est un langage interprété. Kivy utilise Python. En conséquence, pour voir le résultat, vous n'avez pas besoin de compiler le code, exécutez-le - voir / tester. Comme je l'ai dit, Kivy n'utilise pas d'API natives pour le rendu de l'interface utilisateur, il vous permet donc d'émuler différents modèles d'appareils et de plates-formes à l'aide du module d'
écran . Il suffit d'exécuter votre projet avec les paramètres nécessaires pour que la fenêtre de l'application testée s'ouvre sur l'ordinateur comme si elle s'exécutait sur un appareil réel. Cela semble étrange, mais puisque Kivy résume la plate-forme lors du rendu de l'interface utilisateur, cela élimine le besoin d'émulateurs lourds et lents pour les tests. Cela ne s'applique qu'à l'interface utilisateur. Par exemple, l'application de test décrite dans cet article a été testée avec les options d'
écran -m: droid2, portrait, scale = .75 .
A gauche - sur un appareil mobile, à droite - sur un ordinateur:
Liste complète des paramètres du module d'écran: Eh bien, et enfin, le résultat final est le lancement sur un appareil mobile ...
La seule chose qui dérange est la vitesse de lancement. Au même Flutter, elle est tout simplement phénoménale!
J'espère avoir été utile à quelqu'un, à bientôt!