Aller au contenu

Nouveau membre ?! Pense à te présenter pour accéder au contenu du forum !

New member ?! Introduce yourself to get access to the forum !

SkreallyBoy

 tutoriel / partage [Python] Comprendre le fonctionnement des boutons

Messages recommandés

Salut à tous,

 

Alors, ce tutoriel n'a en aucun cas pour but de créer des boutons, mais plus de comprendre comment ça fonctionne derrière ! Car finalement, si vous souhaitez créer des boutons, vous avez juste à copier coller un bout de code dans n'importe quel .py du root et hop c'est réglé, oui mais sinon comment ça fonctionne ? Qu'est-ce qui va permettre au client de faire la différence entre un bouton et une barre de titre ? Ou même encore qu'est-ce qu'un "évènement" ? Eh bien, voyons tout ceci ensemble !

 

1 - Créer un bouton

Avant de partir dans l'explication de comment on crée un bouton on va voir les différents aspects de ce qu'est réellement un bouton. Premièrement voyons pour nous ce qu'est un bouton:

 

Pour nous un bouton c'est:

  • Une image
  • Lorsqu'on clique dessus, ça fait un truc !

Je précise bien évidemment que c'est un abus de langage extrêmement grossier !

 

Mais pour une interface utilisateur (je n'utiliserai plus trop le mot "client" car là, on parle d'interface utilisateur soit l'interface qui va communiquer avec l'utilisateur (le pattern MVC explique bien ce concept)) c'est complètement différent car pour lui une image ce n'est rien d'autre qu'un fichier avec du bytecode, et le "lorsqu'on clic dessus ça fait un truc" bah lui il connait pas ...

 

Donc si on devait un peu mieux expliquer à notre interface utilisateur on pourrait dire ceci :

 

Un bouton c'est :

  • Un membre de l'interface utilisateur (relativement important)
  • Il a plusieurs attributs (image, Hover, Down ...)
  • Il effectue une action

Donc vous l'aurez compris, un bouton, pour l'interface utilisateur, n'est rien d'autres qu'un membre ! Donc pour créer un bouton, il vous suffit de faire :

self.Btoto = ui.Button()
Alors, quelques petites explications sur cette ligne ne serait pas de trop !
  • self : assez souvent utilisé pour dire que ce qui suit après le "." est un membre de la classe, le self représente en réalité l'instance actuelle de la classe qu'on utilise (un peu comme le this en C++).
  • Btoto : Le nom de la variable, notez bien que le python est un langage faiblement typé, c'est à dire qu'il n'y a presque aucun moment où l'on va explicitement donner le type d'une variable quelque part (on appelle ça de la méta programmation) donc généralement, les développeurs, pour éviter de faire n'importe quoi avec les variables donnent des conventions pour définir quelle variable est un nombre, laquelle est une string etc... Ici le "B" veut dire "Button".
  • ui.Button() : C'est en réalité une fonction membre qui retourne un type "Button", comme je vous le disait tout à l'heure : un bouton est bel et bien, un membre de l'interface utilisateur !

Donc ici, nous venons de créer un bouton, il possède donc tous les attributs d'un bouton, mais bon, pour l'instant il n'est pas très bien paramétré ! Essayons de le paramétrer ensemble !

 

2 - Affichons ce petit bouton !

Nous venons de voir comment créer une variable de type "Button", pour autant, il ne s'affichera pas encore, tout simplement parce qu'il n'a même pas de position ou encore d'image ! Cette partie est destinée à montrer comment on fait pour afficher un bouton et même pour le positionner ! Vous allez voir, c'est moins blindé de texte que l'ancienne  :angel: .

 

Comme je l'ai dit tout à l'heure, nous avons créer une variable de type "Button()" mais qu'est-ce que le type "Button" au final ? Eh bien c'est un objet en python qui permet de créer des boutons (oui, pris au mot, cette phrase n'apporte rien au tutoriel). Mais essayons de comprendre, si on a un type bouton qui crée un bouton, ça veut dire que ce type permet d'afficher un bouton, de le positionner...

 

Eh oui ! Car les développeurs de metin² ont bien pensé ! Ils ont donc décidé de mettre en place différentes fonctions membre nous permettant de manipuler la librairie graphique (une surcouche en quelque sorte) et donc tout devient plus simple !

 

Btoto.SetPosition(wndMgr.GetScreenWidth() - 32, wndMgr.GetScreenHeight()/2 - 82)
Alors, là pas grand chose à expliquer, la fonction membre SetPosition prend 2 paramètres (x et y). Et ça va position le bouton aux coordonnées x et y souhaitées !

 

Maintenant voyons comment afficher le bouton !

 

Vous l'aurez deviner il existe aussi une fonction membre pour afficher le bouton, mais pas que ! On peut aussi l'afficher différemment lorsqu'on clic dessus (le DOWN) et lorsque notre curseur est dessus (le HOVER). Normalement le nom des fonctions est relativement explicite :

 

Btoto.SetUpVisual("d:/ymir work/ui/game/taskbar/horse_01.tga") #Lorsque la souris n'est pas dessus
Btoto.SetOverVisual("d:/ymir work/ui/game/taskbar/exp_butt_over.tga") #Lorsque le curseur est dessus
Btoto.SetDownVisual("d:/ymir work/ui/game/taskbar/exp_butt_clicked.tga") #Lorsque l'on clic dessus
Cependant, si vous faites juste ça, il ne s'affichera pas ... Pourquoi ? Tout simplement parce qu'il faut dire explicitement à cet objet de s'afficher, donc comment on fait ça ? Tout simplement avec la fonction membre Show() :
Btoto.Show()
et pour le cacher:
Btoto.Hide()
 
3 - Effectuer une action

Bon c'est bien beau tout ça mais maintenant il s'affiche, l'image change etc... Mais votre bouton, il sert à rien si ce n'est que déranger dans un coin de votre interface ! Pas super sympathique tout ça ... Voyons comment on pourrait faire pour ajouter une action à ce dit bouton !

 

Les event !

 

En informatique ajouter une action à une touche, un clic de souris à des coordonnées ou autre est appelé un event. Généralement ça exécute un bout de code passé en paramètre, ça peut être un script comme une fonction, ou même un lambda. Ici ça peut être soit un lambda ou une fonction.

 

Pour la clarté du tutoriel j'ai choisi d'utiliser une fonction, mais encore une fois, n'oublions pas qu'on manipule un objet de l'UI (User Interface) donc la fonction doit provenir de l'UI. Mais, fort heureusement pour vous, les développeurs ont pensé à tout ! Il ont décidé de créer un autre objet permettant de manipuler une fonction externe à l'UI.

ui.__mem_func__
elle prend en paramètre la fonction que vous souhaitez déclencher lors d'un event. Mais tout ça c'est bien mais du coup comment on set un event ? Eh bien tout simplement comme ceci :
Btoto.SetEvent(ui.__mem_func__(self.handleToto))
le paramètre passé à ui.__mem_func__ est votre fonction que vous souhaitez déclencher lorsqu'on va cliquer sur le bouton, ici handleToto ! Bien évidemment vous devez également créer cette fonction (ouais l'UI est bien développé mais bon faut pas abuser non plus !).

 

Et voilà, vous avez maintenant toutes les petites fonction pour créer un bouton ;) pour plus de propreté du code, je vous conseille vivement de créer votre propre classe contenant ce bouton ainsi que l'évènement !

 

Cordialement,

Partager ce message


Lien à poster
Partager sur d’autres sites

Salut,

 

Tutoriel très bien expliqué, tu as dit tout ce qu'il fallait !

 

Je précise aussi qu'il est préférable de rajouter les informations graphiques dans uiscript, c'est plus "propre" à mon goût et ça reste dans la logique de Metin2. Après tu aurais pu créer une partie test pour savoir si le bouton est fonctionnel en jeu ex :

 

def handleToto(self):
	import chat
	chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.Test)

 

Puis dans "locale_game.txt"

 

Test	Mon bouton fonctionne bien !

 

Après il faut aussi préciser que le bouton doit être bien placé si il est ajouté dans uiscript sur quelque chose de déjà existant (inventaire, costumes, page de statistiques etc...). Par exemple, il faut faire attention d'où le bouton est placé, si il est en dessous d'un autre élément, il pourra être vu graphiquement et inutilisable (non cliquable) ou inversement :/

 

Excellent guide, je suis sûr qu'il servira aux membres qui veulent se lancer là dedans sans spécialement avoir envie de décoder un bouton déjà existant

 

+1 l'ami !

Partager ce message


Lien à poster
Partager sur d’autres sites

Yo galet,

 

Merci de ton commentaire, cependant, d'après ce que tu me dis là, ce n'est pas la même chose qu'un bouton simple, car il y a derrière toute une histoire de sérialisation en Json (cf les fichier tels que taskbar.py etc...).

Je pensais faire un autre tutoriel sur le principe de sérialisation :P à voir ;) mais en ce moment je suis plus à la recherche des fichiers player et item (qui sont des modules python qui m'intéresse pour voir comment le client calcule ses slots).

Partager ce message


Lien à poster
Partager sur d’autres sites

Reyo :D

 

Bah à vrai dire pas spécialement, c'est juste que l'ui est déclarée dans uiscript, qui plus est ça économise pas mal de place et c'est vachement user_friendly car il suffit juste de savoir fouiller et d'avoir un niveau minimum d'anglais, le seul truc un peu chiant c'est le calcul de coordonnées qui en général me prends quelques repacks :/

 

Pro-Tip : Tu peux repacker uiscript en étant en jeu ! Du coup tu as juste à faire ta modification, repack, changer de map et la modification sera prise en compte ! C'est un côté de j'adore très franchement :D

 

{ "name":"NomDuBouton", "type" : "button", "x":CoordonéesX, "y":CoordonéesY, "default_image" : "Image_par_défaut", "over_image" : "Image_Quand_Souris_Dessus", "down_image" : "Image_Quand_Cliquée", },

 

Pour Player et Item, tu ne vas rien trouver de concret dans root, étant donné que le module appelé est comme le module "net" par exemple, il est interne au lanceur, tu peux le trouver dans UserInterface si je ne me trompe pas, dans les fichiers C++ !

Si je ne me trompe pas (j'avais taffé sur les slots y'a deux ans, dans A/Q/S j'avais répondu à quelqu'un qui se posait une question similaire), les slots sont de base limités à 255, ils englobent tous les inventaires possibles et imaginables, shops et entrepôts exclus (Inventaire normal, ceintures & DragonSoul), il faut aussi préciser que tu peux créer des slots visuels dans le client où tu peux mettre des items dedans, mais ces derniers resteront dans l'inventaire et ne se stockeront pas dedans (ex : FastEquip ou SwitchBot)

 

Tu peux aller voir par là, ça peut te guider un peu ! https://funky-emu.net/showthread.php?tid=46625

 

Sinon, petite question, tu es nouveau dans l'émulation ? Tu me sembles être doué

Edit 1 minutes après : Ok j'ai ma réponse à la dernière question xD

Partager ce message


Lien à poster
Partager sur d’autres sites

ReyawYaw

 

Pour ta dernière question ... look tes mp :P

 

Oui je suis d'accord quand au fait que c'est relativement user friendly, mais disons que j'aime bien montrer comment la roue a été inventée avant de parler de IHM ou autre ;) car au final ce n'est qu'un parsing en python sur un fichier JSON et des callbacks, rien de bien méchant :) .

 

Ok je vois les modules items et player sont injectés directement depuis une dll ou whatever donc ? Du coup je peux dire adieu à ma documentation que j'attends :'( . Du coup adieu mon espoir de voir un jour arriver une superbe documentation pour faire ce que je souhaites faire ...

Partager ce message


Lien à poster
Partager sur d’autres sites

ReReYawYoYaw

 

Non ! Ils sont juste en C++ dans les sources du lanceur, donc en clair quoi, si t'as les sources tu peux les voir, je ne vois pas, de mémoire, d'autres emplacement et d'emplacement en python surtout :/

Partager ce message


Lien à poster
Partager sur d’autres sites

ReReYawYoYaw

 

Non ! Ils sont juste en C++ dans les sources du lanceur, donc en clair quoi, si t'as les sources tu peux les voir, je ne vois pas, de mémoire, d'autres emplacement et d'emplacement en python surtout :/

 

D'après la documentation de python, je cite :

 

 

"A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended."

 

Donc normalement il devrait y avoir les .py quelque part, donc je dirai que c'est une inclusion depuis une librairie dynamique charger au lancement (lancement qui doit utiliser la libl si je dis pas de bêtise).

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Bonjour,

 

Tutoriel acceptée, merci de ton investissement !

Partager ce message


Lien à poster
Partager sur d’autres sites

×

Information importante

By using this site, you agree to our Conditions d’utilisation.