Create a FeaturePython object part I/fr: Difference between revisions

From FreeCAD Documentation
No edit summary
No edit summary
 
(108 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<languages/>
<languages/>


{{docnav/fr
{{Docnav/fr
|[[PySide/fr|PySide]]
|[[PySide/fr|PySide]]
|[[Creating a FeaturePython Box, Part II/fr|Création d'un Box FeaturePython, Part II]]
|[[Create_a_FeaturePython_object_part_II/fr|Créer un objet FeaturePython partie II]]
}}
}}


{{TOCright}}
== Introduction ==


==Introduction==
Les objets FeaturePython (également appelés «objets scriptés») offrent aux utilisateurs la possibilité d'étendre FreeCAD avec des objets qui s'intègrent de manière transparente dans le framework FreeCAD.

Les objets FeaturePython (également appelés [[Scripted_objects/fr|Objets créés par script]]) offrent aux utilisateurs la possibilité d'étendre FreeCAD avec des objets qui s'intègrent de manière transparente dans le framework FreeCAD.


Cela favorise:
Cela favorise:
* '''Le prototypage rapide''' de nouveaux objets et outils avec des classes personnalisées de Python.
*Le prototypage rapide de nouveaux objets et outils avec des classes personnalisées de Python.
* '''La sérialisation''' via les objets 'App::Property' ''sans incorporer de scripts'' dans le fichier document FreeCAD.
* Sauvegarde et restauration des données (également appelées sérialisation) via des objets {{incode|App::Property}} sans intégrer de script dans le fichier de document FreeCAD.
* '''Une liberté créative''' pour adapter FreeCAD à n'importe quelle tâche!
*Une liberté créative pour adapter FreeCAD à n'importe quelle tâche.


Ce wiki vous fournira une compréhension complète de l'utilisation des objets FeaturePython et des classes Python personnalisées dans FreeCAD. Nous allons construire un exemple complet et fonctionnel d'une classe personnalisée FeaturePython, identifiant tous les principaux composants et comprendre de manieère fine dont tout cela fonctionne au fur et à mesure.
Sur cette page, nous allons construire un exemple de travail d'une classe personnalisée FeaturePython, en identifiant tous les composants principaux et en comprenant comment tout fonctionne au fur et à mesure.


<span id="How_does_it_work?"></span>
=== Comment ça marche? ===
== Comment ça marche? ==


FreeCAD est fourni avec un certain nombre de types d'objets par défaut pour gérer différents types de géométrie. Certains d'entre eux ont des alternatives 'FeaturePython' qui permettent la personnalisation de l'utilisateur avec une classe python personnalisée.
FreeCAD est livré avec un certain nombre de types d'objets par défaut pour gérer différents types de géométrie. Certains d'entre eux ont des alternatives "FeaturePython" qui permettent une personnalisation avec une classe Python définie par l'utilisateur.


La classe personnalisée de Python prend simplement une référence à l'un de ces objets et le modifie de plusieurs façons. Par exemple, la classe Python peut ajouter des propriétés directement à l'objet, en modifiant d'autres propriétés lorsqu'il est recalculé ou en le liant à d'autres objets. De plus, la classe Python implémente certaines méthodes pour lui permettre de répondre aux événements du document, ce qui permet de piéger les changements de propriétés des objets et les recalculs du document.
Cette classe Python personnalisée prend une référence à l'un de ces objets et le modifie. Par exemple, la classe Python peut ajouter des propriétés à l'objet ou le lier à d'autres objets. De plus, la classe Python peut implémenter certaines méthodes pour permettre à l'objet de répondre aux événements du document, ce qui permet de piéger les modifications de propriété de l'objet et de recalculer le document.


Il est important de se rappeler, cependant, que pour autant que l'on puisse accomplir avec des classes personnalisées et des objets FeaturePython, quand vient le temps d'enregistrer le document, '''seul l'objet FeaturePython lui-même est sérialisé'''. La classe personnalisée et son état ne sont pas conservés entre les rechargements de documents. Cela nécessiterait d'incorporer un script dans le fichier de document FreeCAD, ce qui pose un risque de sécurité important, tout comme les risques posés par [https://www.howtogeek.com/171993/macros-explained-why-microsoft-office-files-can-be-dangerous/ embedding VBA macros in Microsoft Office documents].
Lorsque vous travaillez avec des classes personnalisées et des objets FeaturePython, il est important de savoir que la classe personnalisée et son état ne sont pas enregistrés dans le document car cela nécessiterait l'incorporation d'un script dans un fichier de document FreeCAD, ce qui poserait un risque de sécurité important. Seul l'objet FeaturePython lui-même est enregistré (sérialisé). Mais comme le chemin du module de script est stocké dans le document, un utilisateur n'a qu'à installer le code de classe Python personnalisé en tant que module importable, suivant la même structure de dossier, pour retrouver la fonctionnalité perdue.


[[#top|En haut]]
Ainsi, un objet FeaturePython existe finalement en dehors de son script. L'inconvénient posé par le fait de ne pas empaqueter le script avec l'objet dans le fichier de document est bien moindre que le risque posé par l'exécution d'un fichier incorporé avec un script inconnu. Cependant, le chemin du module de script est stocké dans le fichier de document. Par conséquent, un utilisateur n'a qu'à installer le code de classe python personnalisé en tant que module importable suivant la même structure de répertoires pour retrouver la fonctionnalité perdue.


<span id="Setting_things_up"></span>
== Mise en place ==


Les classes d'objets FeaturePython doivent agir comme des modules importables dans FreeCAD. Cela signifie que vous devez les placer dans un chemin qui existe dans votre environnement Python (ou l'ajouter spécifiquement). Pour les besoins de ce tutoriel, nous allons utiliser le dossier Macro utilisateur FreeCAD, mais si vous avez une autre idée en tête, n'hésitez pas à l'utiliser à la place!
== Configuration de votre environnement de développement ==


Si vous ne savez pas où se trouve le dossier des Macro de FreeCAD, tapez {{incode|FreeCAD.getUserMacroDir(True)}} dans la [[Python_console/fr|console Python]] de FreeCAD :
Pour commencer, les classes d'objets FeaturePython doivent agir comme des modules importables dans FreeCAD. Cela signifie que vous devez les placer dans un chemin qui existe dans votre environnement Python (ou l'ajouter spécifiquement). Pour les besoins de ce tutoriel, nous allons utiliser le dossier Macro utilisateur FreeCAD, mais si vous avez une autre idée en tête, n'hésitez pas à l'utiliser à la place!
* Sous Linux, il s'agit généralement de {{FileName|/home/<username>/.local/share/FreeCAD/Mod/}} ({{VersionPlus/fr|0.20}}) ou {{FileName|/home/<username>/.FreeCAD/Mod/}} ({{VersionMinus/fr|0.19}}).
* Sous Windows, c'est {{FileName|%APPDATA%\FreeCAD\Macro\}}, généralement {{FileName|C:\Users\<username>\Appdata\Roaming\FreeCAD\Macro\}}.
* Sous macOS, il s'agit généralement de {{FileName|/Users/<username>/Library/Application Support/FreeCAD/Macro/}}.


Maintenant, nous devons créer des fichiers :
Si vous ne savez pas où se trouve le dossier Macro FreeCAD, saisissez 'FreeCAD.getUserMacroDir(True)' dans la console Python de FreeCAD. L'endroit est configurable mais, par défaut, pour s'y rendre:
*Dans le dossier {{FileName|Macro}}, créez un nouveau dossier appelé {{FileName|fpo}}.
* Windows: tapez '%APPDATA%/FreeCAD/Macro' dans la barre de chemin de fichier en haut de l'Explorateur
*Dans le dossier {{FileName|fpo}}, créez un fichier vide : {{FileName|__init__.py}}.
* Linux: accédez à /home/USERNAME/.FreeCAD/Macro
*Dans le dossier {{FileName|fpo}}, créez un nouveau dossier appelé {{FileName|box}}.
* Mac: accédez à /Users/USERNAME/Library/Preferences/FreeCAD/Macro
*Dans le dossier {{FileName|box}}, créez deux fichiers : {{FileName|__init__.py}} et {{FileName|box.py}} (laissez les deux cases vides pour l'instant).


La structure de votre dossier devrait ressembler à ceci :
Maintenant, nous devons créer des fichiers.
* Dans le dossier Macro, créez un nouveau dossier appelé '''fpo'''.
* Dans le dossier fpo, créez un fichier vide: '''__init__.py'''.
* Dans le dossier fpo, créez un nouveau dossier appelé '''box'''.
* Dans le dossier de la boîte, créez deux fichiers: '''__init__.py''' et '''box.py''' (laissez les deux vides pour l'instant)


Macro/
Remarques:
|--> fpo/
* Le dossier '''fpo''' fournit un endroit propice pour jouer avec les nouveaux objets FeaturePython et le dossier '''box''' est le module dans lequel nous travaillerons.
|--> __init__.py
* ''''__init__.py''' indique à Python que dans le dossier se trouve un module importable et '''box.py''' sera le fichier de classe pour notre nouvel objet FeaturePython.
|--> box/
|--> __init__.py
|--> box.py


Le dossier {{FileName|fpo}} est l'endroit pour jouer avec les nouveaux objets FeaturePython et le dossier {{FileName|box}} est le module dans lequel nous allons travailler. {{FileName|__init__.py}} indique à Python qu'il y a un module importable dans le dossier et {{FileName|box.py}} sera le fichier de classe pour notre nouvel objet FeaturePython.
La structure de votre répertoire devrait ressembler à ceci:


Une fois nos chemins et fichiers de module créés, nous assurons que FreeCAD est correctement configuré :
.FreeCAD
* Démarrez FreeCAD (si vous ne l'avez pas déjà fait).
|--> Macro
* Activez la [[Report_view/fr|Vue rapport]] ({{MenuCommand|Affichage → Panneaux → Vue rapport}}).
|--> fpo
* Activez la [[Python_console/fr|console Python]] ({{MenuCommand|Affichage → Panneaux → Console Python}}) voir [[FreeCAD_Scripting_Basics/fr|FreeCAD Scripting Basics]].
|--> __init__.py
|--> box
|--> __init__.py
|--> box.py


Enfin, naviguez jusqu'au dossier {{FileName|Macro/fpo/box}} et ouvrez {{FileName|box.py}} dans votre éditeur de code préféré. Nous ne modifierons que ce fichier.
Avec nos chemins de modules et fichiers créés, assurez-vous que FreeCAD est correctement configuré:


[[#top|En haut]]
* Démarrez FreeCAD (s'il n'est pas déjà ouvert)
* Activer la console Python et les vues de rapport ('''Affichage -> Panneaux -> Vue rapport''' et '''console Python''') [[FreeCAD Scripting Basics/fr|(FreeCAD Débuter avec les scripts)]]
* Dans votre éditeur de code préféré, accédez au dossier '''/Macro/fpo/box''' et ouvrez '''box.py'''


<span id="A_FeaturePython_object"></span>
Il est temps d'écrire du code!
==Un objet FeaturePython==


Commençons par écrire notre classe et son constructeur :


{{Code|code=
-----
class box():


def __init__(self, obj):
== Un objet FeaturePython très basique ==
"""
Default constructor
"""


self.Type = 'box'
Commençons par écrire notre classe et son constructeur:


obj.Proxy = self
class box():
}}
def __init__(self, obj):
"""
Constructor
Arguments
---------
- obj: a variable created with FreeCAD.Document.addObject('App::FeaturePython', '{name}').
"""
self.Type = 'box'
obj.Proxy = self


'''La méthode {{incode|__init__()}} se décompose comme suit:'''


{|class="wikitable" cellpadding="5px" width="100%"
'''La méthode breakdown <code>__init__()</code>'''
|style="width:25%" | {{incode|def __init__(self, obj):}}
{|class="wikitable" cellpadding="5" style="margin-left: 15px; margin-right: 5px"
|style="width:30%" | <code>def __init__(self, obj):</code> || Les paramètres font référence à la classe Python elle-même et à l'objet FeaturePython auquel elle est attachée.
|style="width:75%" | Les paramètres font référence à la classe Python elle-même et à l'objet FeaturePython auquel elle est attachée.
|-
|-
| {{incode|self.Type <nowiki>=</nowiki> 'box'}}
|<code> self.Type = 'box'</code> || Définition de chaîne du type Python personnalisé.
| Définition de chaîne du type Python personnalisé.
|-
|-
| {{incode|obj.Proxy <nowiki>=</nowiki> self}}
|<code> obj.Proxy = self</code> || Stocke une référence à l'instance Python dans l'objet FeaturePython.
| Stocke une référence à l'instance Python dans l'objet FeaturePython.
|}
|}


Ajoutez le code suivant en haut du fichier :


{{Code|code=
Dans le fichier '''box.py''' en haut, ajoutez le code suivant:
import FreeCAD as App


def create(obj_name):
import FreeCAD as App
"""
Object creation method
def create(obj_name):
"""
"""
Object creation method
"""
obj = App.ActiveDocument.addObject('App::FeaturePython', obj_name)
fpo = box(obj)
return obj


obj = App.ActiveDocument.addObject('App::FeaturePython', obj_name)


box(obj)
'''La méthode breakdown <code>create()</code>'''

{|class="wikitable" cellpadding="5" style="float:right; margin-left: 15px; margin-right: 5px"
return obj
|style="width:30%" | <code>import FreeCAD as App</code> || Importation standard pour la plupart des scripts python. L'alias '''App''' n'est pas requis.
}}

'''La méthode {{incode|create()}} se décompose comme suit :'''

{|class="wikitable" cellpadding="5px" width="100%"
|style="width:25%" | {{incode|import FreeCAD as App}}
|style="width:75%" | Importation standard pour la plupart des scripts Python, l'alias d'application n'est pas requis.
|-
|-
| {{incode|obj <nowiki>=</nowiki> ... addObject(...)}}
|<code>obj = ... addObject(...)</code> || Crée un nouvel objet FreeCAD FeaturePython avec le nom transmis à la méthode. S'il n'y a pas de conflit de noms, ce sera l'étiquette et le nom de l'objet créé, c'est-à-dire ce qui est visible dans l'arbre du modèle. Sinon, un nom et une étiquette uniques seront créés sur la base de 'nom_obj'.
| Crée un nouvel objet FeaturePython de FreeCAD avec le nom transmis à la méthode. S'il n'y a pas de conflit de nom, ce sera le libellé et le nom de l'objet créé. Sinon, un nom et une étiquette uniques seront créés en fonction de 'obj_name'.
|-
|-
| {{incode|box(obj)}}
|<code>fpo = box(obj)</code> || Créez l'instance de classe personnalisée et liez-la à l'objet FeaturePython.
| Crée notre instance de classe personnalisée.
|-
| {{incode|return obj}}
| Renvoie l'objet FeaturePython.
|}
|}


La méthode {{incode|create()}} n'est pas requise mais elle fournit un bon moyen d'encapsuler le code de création d'objet.


[[#top|En haut]]
La méthode <code>create()</code> n'est pas requise mais elle fournit un bon moyen d'encapsuler le code de création d'objet.


<span id="Testing_the_code"></span>
=== Test du code ===


Nous pouvons maintenant tester notre nouvel objet. Enregistrez votre code et revenez à FreeCAD. Assurez-vous que vous avez ouvert un nouveau document, vous pouvez le faire en appuyant sur {{KEY|Ctrl}}+{{KEY|N}} ou en sélectionnant {{MenuCommand|Fichier → Nouveau}}.
-----


Dans la console Python, tapez ce qui suit :
=== Test du code ===


{{Code|code=
Maintenant, nous pouvons essayer notre nouvel objet. Enregistrez votre code et revenez à FreeCAD, assurez-vous d'avoir '''ouvert un nouveau document'''. Vous pouvez le faire en appuyant sur '''CTRL+n''' ou en sélectionnant '''Fichier -> Nouveau'''
from fpo.box import box
}}


Maintenant, nous devons créer notre objet :
Dans la console Python, tapez ce qui suit:


{{Code|code=
>>> from fpo.box import box
mybox = box.create('my_box')
}}


[[Image:Fpo_treeview.png|right]]
<br>Maintenant, nous devons créer notre objet:
Vous devriez voir apparaître un nouvel objet dans la [[Tree_view/fr|Vue en arborescence]] étiqueté "my_box".


Notez que l'icône est grise. FreeCAD nous dit que l'objet ne peut rien afficher dans la [[3D_view/fr|Vue 3D]]. Cliquez sur l'objet et regardez ses propriétés dans l'[[Property_editor/fr|Éditeur de propriétés]]. Il n'y a pas grand-chose là-bas, juste le nom de l'objet.
>>> box.create('my_box')


Notez également qu'il y a une petite coche bleue à côté de l'objet FeaturePython dans l'arborescence. En effet, lorsqu'un objet est créé ou modifié, il est "touché" et doit être recalculé. Appuyez sur le bouton {{Button|[[Image:Std_Refresh.svg|16px]] [[Std_Refresh/fr|Std Rafraîchir]]}} pour y parvenir. Nous ajouterons du code pour automatiser cela plus tard.
[[File:Fpo_treeview.png | right | 192px]]
{{Clear}}
Vous devriez voir un nouvel objet apparaître dans l'arborescence en haut à gauche intitulé '''my_box'''.<br><br>Notez que l'icône est grise. FreeCAD nous dit simplement que l'objet n'est pas en mesure d'afficher quoi que ce soit dans la vue 3D... pour l'instant. Cliquez sur l'objet et notez ce qui apparaît dans le panneau de propriétés en dessous. <br>Il n'y a pas grand-chose juste le nom de l'objet. Nous devrons ajouter quelques propriétés sous peu.
<br clear="all">
Rendons également le référencement de notre nouvel objet un peu plus pratique:


Jetons un oeil aux attributs de notre objet :
>>> mybox = App.ActiveDocument.my_box
{{Code|code=
dir(mybox)
}}


Cela retournera :
Et puis nous devrions jeter un oeil aux attributs de notre objet:


{{Code|code=
>>> dir(mybox)
['Content', 'Document', 'ExpressionEngine', 'InList', 'InListRecursive', 'Label', 'MemSize', 'Module', 'Name', 'OutList', 'OutListRecursive', 'PropertiesList', 'Proxy', 'State', 'TypeId', 'ViewObject', '__class__',
['Content', 'Document', 'ExpressionEngine', 'FullName', 'ID', 'InList',
...
...
'setEditorMode', 'setExpression', 'supportedProperties', 'touch']
'setPropertyStatus', 'supportedProperties', 'touch']
}}


Il y a beaucoup d'attributs car nous accédons à l'objet FeaturePyton natif de FreeCAD créé à la première ligne de notre méthode {{incode|create()}}. La propriété {{incode|Proxy}} que nous avons ajoutée dans notre méthode {{incode|__init__()}} est là aussi.


Inspectons-la avec la méthode {{incode|dir()}} :
Il y a beaucoup d'attributs parce que nous accédons à l'objet FreeCAD FeaturePyton natif que nous avons créé dans la première ligne de notre <code>create()</code> méthode.
La propriété <code>Proxy</code> que nous avons ajoutée dans notre méthode <code>__init__()</code> est également là.


{{Code|code=
Inspectons cela en appelant le <code>dir()</code>sur l'objet Proxy:
dir(mybox.Proxy)
}}


Cela retournera :
>>> dir(mybox.Proxy)
['Object', 'Type', '__class__', '__delattr__', '__dict__', '__dir__',
...
'__str__', '__subclasshook__', '__weakref__']


{{Code|code=
['Type', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
...
'__str__', '__subclasshook__', '__weakref__']
}}


Nous pouvons voir notre propriété {{incode|Type}}. Vérifions :
Une fois que nous avons inspecté la propriété Proxy, nous pouvons voir notre <code>Object</code> et <code>Type</code> propriétés. Cela signifie que nous accédons à l'objet Python personnalisé défini dans '''box.py'''.


{{Code|code=
Appelez la propriété <code>Type</code> et regardez le résultat:
>>> mybox.Proxy.Type
mybox.Proxy.Type
}}
'box'


Cela retournera :
Bien sûr, il retourne la valeur que nous avons assignée, donc nous savons que nous accédons à la classe personnalisée elle-même par le biais de l'objet FeaturePython.


{{Code|code=
De même, nous pouvons accéder à l'objet FreeCAD (pas à notre objet Python) en utilisant le<code>Object</code>méthode:
'box'
>>> mybox.Proxy.Object
}}


Il s'agit bien de la valeur assignée, nous savons donc que nous accédons à la classe personnalisée via l'objet FeaturePython.
C'était amusant! Mais voyons maintenant si nous pouvons rendre notre classe un peu plus intéressante ... et peut-être plus utile.


Voyons maintenant si nous pouvons rendre notre classe un peu plus intéressante, et peut-être aussi plus utile.


[[#top|En haut]]
-----


<span id="Adding_properties"></span>
=== Ajout de propriétés ===
===Ajout de propriétés===


Les propriétés sont l'élément vital d'une classe FeaturePython. Heureusement, FreeCAD supporte [[FeaturePython_Custom_Properties/fr|un certain nombre de types de propriétés]] pour les classes FeaturePython. Ces propriétés sont attachées directement à l'objet FeaturePython et sont entièrement sérialisées lors de l'enregistrement du fichier. Pour éviter d'avoir à sérialiser les données vous-même, il est conseillé de n'utiliser que ces types de propriétés.
Les propriétés sont l'élément vital d'une classe FeaturePython.
<br><br> Heureusement, FreeCAD prend en charge [[FeaturePython_Custom_Properties/fr|un certain nombre de types de propriétés personnalisées de FeaturePython]] pour les classes FeaturePython. Ces propriétés sont attachées directement à l'objet FeaturePython lui-même et entièrement sérialisées lorsque le fichier est enregistré. Cela signifie que, sauf si vous souhaitez sérialiser les données vous-même, vous devrez trouver un moyen de les ancrer dans un type de propriété pris en charge.
<br><br> L'ajout de propriétés se fait tout simplement en utilisant le <code>add_property()</code> méthode. La syntaxe de la méthode est:


L'ajout de propriétés se fait à l'aide de la méthode {{incode|add_property()}}. La syntaxe de cette méthode est la suivante :

<!--Ne pas utiliser de modèle de code pour éviter la mise en évidence de la syntaxe-->
add_property(type, name, section, description)
add_property(type, name, section, description)


Vous pouvez consulter la liste des propriétés prises en charge en tapant :
{|class="wikitable" cellpadding="5" style="float:right; margin-left: 15px; margin-right: 5px; text-align:left"
!Tip
|-
||Vous pouvez afficher la liste des propriétés prises en charge pour un objet en tapant:<br><code>>>> mybox.supportedProperties()</code>
|}
<br>Essayons d'ajouter une propriété à notre classe box.
<br><br>Basculez vers votre éditeur de code et passez à la <code>__init__()</code> méthode.


{{Code|code=
<br clear="all">Ensuite, à la fin de la méthode, ajoutez:
mybox.supportedProperties()
}}


Essayons d'ajouter une propriété à notre classe de boîte. Passez à votre éditeur de code, passez à la méthode {{incode|__init__()}}, et à la fin de la méthode, ajoutez :
obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = ""
Notez comment nous utilisons la référence à l'objet FeaturePython (sérialisable), <code>obj</code> et non l'instance de classe Python (non sérialisable), <code>self</code><br>Quoi qu'il en soit, une fois que vous avez terminé, enregistrez les modifications et revenez à FreeCAD.
<br><br>Avant de pouvoir observer les modifications que nous avons apportées à notre code, nous devons recharger le module. Cela peut être accompli en redémarrant FreeCAD, mais le redémarrage de FreeCAD chaque fois que nous apportons une modification au code de classe python peut devenir un peu gênant. Pour le rendre plus facile, essayez ce qui suit dans la console Python:


{{Code|code=
>>> from importlib import reload
obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = ""
>>> reload(box)
}}
Cela rechargera le module box, incorporant les modifications que vous avez apportées au fichier '''box.py''' comme si vous aviez redémarré FreeCAD.
<br><br>Le module étant rechargé, voyons maintenant ce que nous obtenons lorsque nous créons un objet:


Notez que nous utilisons la référence à l'objet FeaturePython (sérialisable) {{incode|obj}}, et non l'instance de classe Python (non sérialisable) {{incode|self}}.
>>> box.create('box_property_test')
[[File:fpo_properties.png | right | 320px]]Vous devriez voir le nouvel objet boîte apparaître dans l'arborescence à gauche.<br><br>
*Sélectionnez-le et regardez le panneau des propriétés. Là, vous devriez voir la propriété 'Description'.<br>
*Passez la souris sur le nom de la propriété à gauche et voyez l'infobulle apparaître avec le texte de description que vous avez fourni.<br>
*Sélectionnez le champ et saisissez ce que vous voulez. Vous remarquerez que les commandes de mise à jour Python sont exécutées et affichées dans la console lorsque vous tapez des lettres et que la propriété change.
<br><br>Mais avant de quitter le sujet des propriétés pour le moment, revenons en arrière et ajoutons quelques propriétés qui rendraient un objet boîte personnalisé *vraiment* utile: à savoir ''length'', ''width'' et ''height''.
<br><br>Revenez à votre code source et ajoutez les propriétés suivantes à <code>__init__()</code>:


Une fois que vous avez terminé, enregistrez les modifications et revenez à FreeCAD. Avant de pouvoir observer les modifications apportées à notre code, nous devons recharger le module. Cela peut être accompli en redémarrant FreeCAD, mais redémarrer FreeCAD à chaque fois que nous éditons le code serait gênant. Pour faciliter les choses, tapez ce qui suit dans la console Python :
obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = '10 mm'
obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = '1 cm'


{{Code|code=
[[File:object_recompute_icon.png | left | 64px]]Une dernière chose: avez-vous remarqué comment la coche bleue apparaît à côté de l'objet FeaturePython dans l'arborescence à gauche?
from importlib import reload
En effet, lorsqu'un objet est créé ou modifié, il est "touché" et doit être recalculé. Cliquer sur les flèches "recycler" (les deux flèches formant un cercle) accomplira cela.
reload(box)
<br><br>Mais nous pouvons accomplir cela automatiquement en ajoutant la ligne suivante à la fin du <code>create()</code> méthode:
}}


Avec le module rechargé, voyons ce que nous obtenons lorsque nous créons un objet :
App.ActiveDocument.recompute()

{|class="wikitable" cellpadding="5" style="margin-left: 15px; margin-right: 15px; text-align:left"
{{Code|code=
!Remarque
box.create('box_property_test')
|-
}}
|Soyez prudent lorsque vous recalculez un objet FeaturePython! En règle générale, vous ne devez pas essayer de recalculer un objet de l'intérieur de lui-même. Le recalcul des documents doit plutôt être géré par une méthode externe à l'objet, si possible.

|}
Vous devriez voir le nouvel objet boîte apparaître dans l'arborescence :
<br>Maintenant, testez vos modifications comme suit:<br>
*Sélectionnez-le et regardez l'éditeur de propriétés. Là, vous devriez voir la propriété ''Description''.
*Enregistrez vos modifications et revenez à FreeCAD.<br>
*Passez la souris sur le nom de la propriété à gauche et l'info-bulle devrait apparaître avec la description que vous avez fournie.
*Supprimez tous les objets existants et rechargez votre module.<br>
*Sélectionnez le champ et tapez ce que vous voulez. Vous remarquerez que les commandes de mise à jour Python sont exécutées et affichées dans la console lorsque vous tapez des lettres et que les propriétés changent.
*Enfin, créez un autre objet boîte à partir de la ligne de commande en appelant <code>>>> box.create('myBox')</code>[[File:fpo_box_properties.png | right | 320px]]

<br>Une fois la boîte créée (et vous avez vérifié qu'elle a bien été recalculée!), sélectionnez l'objet et examinez vos propriétés.
[[#top|En haut]]
<br>Vous devriez noter deux choses: <br>

*Trois nouvelles propriétés (''length'', ''width'', and ''height'')
Ajoutons quelques propriétés supplémentaires. Retournez à votre code source et ajoutez les propriétés suivantes à la méthode {{incode|__init__()}} :
*Un nouveau groupe de propriétés,''Dimensions''.

<br>Notez également comment les propriétés ont des dimensions. Plus précisément, ils prennent la dimension linéaire des unités définies dans les préférences de l'utilisateur (voir '''Modifier''' -> '''Préférence ...''' -> '''Onglet Unités''').
{{Code|code=
<br clear="all"><br>En fait, si vous faites attention lors de la saisie du code, vous aurez remarqué que trois valeurs distinctes ont été saisies pour chaque dimension. La longueur était une valeur à virgule flottante (10.0), la largeur était une chaîne, spécifiant les millimètres ('10 mm') et la hauteur était une chaîne spécifiant les centimètres ('1 cm'). Pourtant, la propriété a rendu les trois valeurs de la même manière: 10 mm. Plus précisément, une valeur à virgule flottante est supposée être dans les unités de document actuelles, et les valeurs de chaîne sont analysées selon les unités spécifiées, puis converties en unités de document.
obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
<br><br>Ce qui est bien avec le type <code>App::PropertyLength</code>, c'est qu'il s'agit d'un type 'unit'. Les valeurs sont comprises comme ayant des unités spécifiques. Par conséquent, chaque fois que vous créez une propriété qui utilise des dimensions linéaires, utilisez <code>App::PropertyLength</code> comme type de propriété.
obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = '10 mm'
obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = '1 cm'
}}

Et ajoutons aussi un code pour recalculer le document automatiquement. Ajoutez la ligne suivante au-dessus de l'instruction {{incode|return()}} de la méthode {{incode|create()}}:

{{Code|code=
App.ActiveDocument.recompute()
}}

'''Faites attention à l'endroit où vous recalculez un objet FeaturePython. Le recalcul doit être effectué par une méthode externe à sa classe.'''

[[Image:fpo_box_properties.png | right]]

Maintenant, testez vos modifications comme suit:
* Enregistrez vos modifications et rechargez votre module.
* Supprimez tous les objets dans l'arborescence.
* Créez un nouvel objet boîte à partir de la console Python en appelant {{incode|box.create('myBox')}}.

Une fois que la boîte est créée et que vous avez vérifié pour vous assurer qu'elle a été recalculée, sélectionnez l'objet et regardez ses propriétés. Vous devez noter deux choses:
* Un nouveau groupe de propriétés: ''Dimensions''.
* Trois nouvelles propriétés: ''Height'', ''Length'' et ''Width''.

Notez également que les propriétés ont des unités. Plus précisément, elles ont repris les unités linéaires définies dans les préférences de l'utilisateur ({{MenuCommand|Edition → Préférences... → Général → Unités}}).
{{Clear}}


Vous avez sans doute remarqué que trois valeurs différentes ont été saisies pour les dimensions : une valeur en virgule flottante ({{incode|10.0}}) et deux chaînes de caractères différentes ({{incode|'10 mm'}} et {{incode|'1 cm'}}). Le type {{incode|App::PropertyLength}} suppose que les valeurs en virgule flottante sont en millimètres, les valeurs des chaînes sont analysées en fonction des unités spécifiées et, dans l'interface graphique, toutes les valeurs sont converties dans les unités spécifiées dans les préférences de l'utilisateur ({{incode|mm}} dans l'image). Ce comportement intégré rend le type {{incode|App::PropertyLength}} idéal pour les dimensions.


[[#top|En haut]]
-----


<span id="Trapping_events"></span>
=== Piège à événements ===
=== Piège à événements ===


Le dernier élément requis pour un objet FeaturePython de base est le piégeage des événements. Plus précisément, nous devons piéger l'événement <code>execute()</code>, qui est appelé lorsque l'objet est recalculé. Il y a plusieurs autres événements au niveau du document qui peuvent être piégés dans notre objet, à la fois dans l'objet FeaturePython lui-même et dans le ViewProvider, que nous couvrirons dans une autre section.
Le dernier élément requis pour un objet FeaturePython de base est le recouvrement d'événements. Un objet FeaturePython peut réagir aux événements avec des fonctions de rappel. Dans notre cas, nous voulons que l'objet réagisse chaque fois qu'il est recalculé. En d'autres termes, nous voulons intercepter les recalculs. Pour ce faire, nous devons ajouter une fonction avec un nom spécifique, {{incode|execute()}}, à la classe d'objets. Il existe plusieurs autres événements qui peuvent être piégés, à la fois dans l'objet FeaturePython lui-même et dans le [[Viewprovider/fr|ViewProvider]], que nous aborderons dans la [[Create_a_FeaturePython_object_part_II/fr|Création d'une boîte FeaturePython, partie II]].
<br>
Ajoutez ce qui suit après la fonction <code>__init__()</code>:


Pour une référence complète des méthodes disponibles à implémenter sur les classes FeautrePython, voir [[FeaturePython_methods/fr|Méthodes FeaturePython]].
def execute(self, obj):
"""
Called on document recompute
"""
print('Recomputing {0:s} ({1:s})'.format(obj.Name, self.Type))


Ajoutez ce qui suit après la fonction {{incode|__init__()}}:


{{Code|code=
Testez le code comme suit:
def execute(self, obj):
*Enregistrez les modifications et rechargez le module box dans la console python FreeCAD.
"""
*Supprimer tous les objets dans l'arborescence.
Called on document recompute
*Recréez l'objet boîte.
"""


print('Recomputing {0:s} ({1:s})'.format(obj.Name, self.Type))
Vous devriez voir le résultat dans la console Python, grâce à l'appel <code>recompute()</code> que nous avons ajouté à la méthode <code>create()</code>.
}}


Testez le code en suivant à nouveau ces étapes:
Bien sûr, la méthode <code>execute()</code> ne fait rien ici (sauf nous dire qu'elle a été appelée), mais c'est la clé de la magie des objets FeaturePython.
*Enregistrez et rechargez le module.
*Supprimer tous les objets.
*Créez un nouvel objet boîte.


Vous devriez voir la sortie imprimée dans la console Python, grâce à l'appel {{incode|recompute()}} que nous avons ajouté à la méthode {{incode|create()}}. Bien sûr, la méthode {{incode|execute()}} ne fait rien ici, sauf nous dire qu'elle a été appelée, mais elle est la clé de la magie des objets FeaturePython.
<br>'''Et voilà!'''
<br>Vous savez maintenant comment construire un objet FeaturePython basique et fonctionnel!


Voilà, vous savez maintenant comment construire un objet FeaturePython basique et fonctionnel !


[[#top|En haut]]
-----


<span id="Complete_code"></span>
=== Le code terminé ===
=== Le code terminé ===

import FreeCAD as App
{{Code|code=
import FreeCAD as App
def create(obj_name):

def create(obj_name):
"""
"""
Object creation method
Object creation method
"""
"""

obj = App.ActiveDocument.addObject('App::FeaturePython', obj_name))
obj = App.ActiveDocument.addObject('App::FeaturePython', obj_name)

fpo = box(obj)
box(obj)

App.ActiveDocument.recompute()

return obj
return obj

class box():
class box():

def __init__(self, obj):
def __init__(self, obj):
"""
"""
Default Constructor
Default constructor
"""
"""

self.Type = 'box'
self.Type = 'box'

obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = ""
obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = '10 mm'
obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = '1 cm'
obj.Proxy = self
obj.Proxy = self

obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = ""
obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = '10 mm'
obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = '1 cm'

def execute(self, obj):
def execute(self, obj):
"""
"""
Called on document recompute
Called on document recompute
"""
"""

print('Recomputing {0:s} {1:s}'.format(obj.Name, self.Type))
print('Recomputing {0:s} ({1:s})'.format(obj.Name, self.Type))
{{docnav/fr
|[[PySide/fr|PySide]]
|[[Creating a FeaturePython Box, Part II/fr|Création d'un Box FeaturePython, Part II]]
}}
}}


[[#top|En haut]]
{{Userdocnavi/fr}}

{{Docnav/fr
|[[PySide/fr|PySide]]
|[[Create_a_FeaturePython_object_part_II/fr|Créer un objet FeaturePython partie II]]
}}


[[Category:Poweruser Documentation/fr]]


{{Powerdocnavi{{#translation:}}}}
[[Category:Python Code/fr]]
[[Category:Developer Documentation{{#translation:}}]]
[[Category:Python Code{{#translation:}}]]
{{clear}}

Latest revision as of 09:47, 18 February 2023

Other languages:

Introduction

Les objets FeaturePython (également appelés Objets créés par script) offrent aux utilisateurs la possibilité d'étendre FreeCAD avec des objets qui s'intègrent de manière transparente dans le framework FreeCAD.

Cela favorise:

  • Le prototypage rapide de nouveaux objets et outils avec des classes personnalisées de Python.
  • Sauvegarde et restauration des données (également appelées sérialisation) via des objets App::Property sans intégrer de script dans le fichier de document FreeCAD.
  • Une liberté créative pour adapter FreeCAD à n'importe quelle tâche.

Sur cette page, nous allons construire un exemple de travail d'une classe personnalisée FeaturePython, en identifiant tous les composants principaux et en comprenant comment tout fonctionne au fur et à mesure.

Comment ça marche?

FreeCAD est livré avec un certain nombre de types d'objets par défaut pour gérer différents types de géométrie. Certains d'entre eux ont des alternatives "FeaturePython" qui permettent une personnalisation avec une classe Python définie par l'utilisateur.

Cette classe Python personnalisée prend une référence à l'un de ces objets et le modifie. Par exemple, la classe Python peut ajouter des propriétés à l'objet ou le lier à d'autres objets. De plus, la classe Python peut implémenter certaines méthodes pour permettre à l'objet de répondre aux événements du document, ce qui permet de piéger les modifications de propriété de l'objet et de recalculer le document.

Lorsque vous travaillez avec des classes personnalisées et des objets FeaturePython, il est important de savoir que la classe personnalisée et son état ne sont pas enregistrés dans le document car cela nécessiterait l'incorporation d'un script dans un fichier de document FreeCAD, ce qui poserait un risque de sécurité important. Seul l'objet FeaturePython lui-même est enregistré (sérialisé). Mais comme le chemin du module de script est stocké dans le document, un utilisateur n'a qu'à installer le code de classe Python personnalisé en tant que module importable, suivant la même structure de dossier, pour retrouver la fonctionnalité perdue.

En haut

Mise en place

Les classes d'objets FeaturePython doivent agir comme des modules importables dans FreeCAD. Cela signifie que vous devez les placer dans un chemin qui existe dans votre environnement Python (ou l'ajouter spécifiquement). Pour les besoins de ce tutoriel, nous allons utiliser le dossier Macro utilisateur FreeCAD, mais si vous avez une autre idée en tête, n'hésitez pas à l'utiliser à la place!

Si vous ne savez pas où se trouve le dossier des Macro de FreeCAD, tapez FreeCAD.getUserMacroDir(True) dans la console Python de FreeCAD :

  • Sous Linux, il s'agit généralement de /home/<username>/.local/share/FreeCAD/Mod/ (version 0.20 et suivantes) ou /home/<username>/.FreeCAD/Mod/ (version 0.19 et précédentes).
  • Sous Windows, c'est %APPDATA%\FreeCAD\Macro\, généralement C:\Users\<username>\Appdata\Roaming\FreeCAD\Macro\.
  • Sous macOS, il s'agit généralement de /Users/<username>/Library/Application Support/FreeCAD/Macro/.

Maintenant, nous devons créer des fichiers :

  • Dans le dossier Macro, créez un nouveau dossier appelé fpo.
  • Dans le dossier fpo, créez un fichier vide : __init__.py.
  • Dans le dossier fpo, créez un nouveau dossier appelé box.
  • Dans le dossier box, créez deux fichiers : __init__.py et box.py (laissez les deux cases vides pour l'instant).

La structure de votre dossier devrait ressembler à ceci :

Macro/
    |--> fpo/
        |--> __init__.py
        |--> box/
            |--> __init__.py
            |--> box.py

Le dossier fpo est l'endroit pour jouer avec les nouveaux objets FeaturePython et le dossier box est le module dans lequel nous allons travailler. __init__.py indique à Python qu'il y a un module importable dans le dossier et box.py sera le fichier de classe pour notre nouvel objet FeaturePython.

Une fois nos chemins et fichiers de module créés, nous assurons que FreeCAD est correctement configuré :

Enfin, naviguez jusqu'au dossier Macro/fpo/box et ouvrez box.py dans votre éditeur de code préféré. Nous ne modifierons que ce fichier.

En haut

Un objet FeaturePython

Commençons par écrire notre classe et son constructeur :

class box():

    def __init__(self, obj):
        """
        Default constructor
        """

        self.Type = 'box'

        obj.Proxy = self

La méthode __init__() se décompose comme suit:

def __init__(self, obj): Les paramètres font référence à la classe Python elle-même et à l'objet FeaturePython auquel elle est attachée.
self.Type = 'box' Définition de chaîne du type Python personnalisé.
obj.Proxy = self Stocke une référence à l'instance Python dans l'objet FeaturePython.

Ajoutez le code suivant en haut du fichier :

import FreeCAD as App

def create(obj_name):
    """
    Object creation method
    """

    obj = App.ActiveDocument.addObject('App::FeaturePython', obj_name)

    box(obj)

    return obj

La méthode create() se décompose comme suit :

import FreeCAD as App Importation standard pour la plupart des scripts Python, l'alias d'application n'est pas requis.
obj = ... addObject(...) Crée un nouvel objet FeaturePython de FreeCAD avec le nom transmis à la méthode. S'il n'y a pas de conflit de nom, ce sera le libellé et le nom de l'objet créé. Sinon, un nom et une étiquette uniques seront créés en fonction de 'obj_name'.
box(obj) Crée notre instance de classe personnalisée.
return obj Renvoie l'objet FeaturePython.

La méthode create() n'est pas requise mais elle fournit un bon moyen d'encapsuler le code de création d'objet.

En haut

Test du code

Nous pouvons maintenant tester notre nouvel objet. Enregistrez votre code et revenez à FreeCAD. Assurez-vous que vous avez ouvert un nouveau document, vous pouvez le faire en appuyant sur Ctrl+N ou en sélectionnant Fichier → Nouveau.

Dans la console Python, tapez ce qui suit :

from fpo.box import box

Maintenant, nous devons créer notre objet :

mybox = box.create('my_box')

Vous devriez voir apparaître un nouvel objet dans la Vue en arborescence étiqueté "my_box".

Notez que l'icône est grise. FreeCAD nous dit que l'objet ne peut rien afficher dans la Vue 3D. Cliquez sur l'objet et regardez ses propriétés dans l'Éditeur de propriétés. Il n'y a pas grand-chose là-bas, juste le nom de l'objet.

Notez également qu'il y a une petite coche bleue à côté de l'objet FeaturePython dans l'arborescence. En effet, lorsqu'un objet est créé ou modifié, il est "touché" et doit être recalculé. Appuyez sur le bouton Std Rafraîchir pour y parvenir. Nous ajouterons du code pour automatiser cela plus tard.

Jetons un oeil aux attributs de notre objet :

dir(mybox)

Cela retournera :

['Content', 'Document', 'ExpressionEngine', 'FullName', 'ID', 'InList',
...
'setPropertyStatus', 'supportedProperties', 'touch']

Il y a beaucoup d'attributs car nous accédons à l'objet FeaturePyton natif de FreeCAD créé à la première ligne de notre méthode create(). La propriété Proxy que nous avons ajoutée dans notre méthode __init__() est là aussi.

Inspectons-la avec la méthode dir() :

dir(mybox.Proxy)

Cela retournera :

['Type', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
...
'__str__', '__subclasshook__', '__weakref__']

Nous pouvons voir notre propriété Type. Vérifions :

mybox.Proxy.Type

Cela retournera :

'box'

Il s'agit bien de la valeur assignée, nous savons donc que nous accédons à la classe personnalisée via l'objet FeaturePython.

Voyons maintenant si nous pouvons rendre notre classe un peu plus intéressante, et peut-être aussi plus utile.

En haut

Ajout de propriétés

Les propriétés sont l'élément vital d'une classe FeaturePython. Heureusement, FreeCAD supporte un certain nombre de types de propriétés pour les classes FeaturePython. Ces propriétés sont attachées directement à l'objet FeaturePython et sont entièrement sérialisées lors de l'enregistrement du fichier. Pour éviter d'avoir à sérialiser les données vous-même, il est conseillé de n'utiliser que ces types de propriétés.

L'ajout de propriétés se fait à l'aide de la méthode add_property(). La syntaxe de cette méthode est la suivante :

add_property(type, name, section, description)

Vous pouvez consulter la liste des propriétés prises en charge en tapant :

mybox.supportedProperties()

Essayons d'ajouter une propriété à notre classe de boîte. Passez à votre éditeur de code, passez à la méthode __init__(), et à la fin de la méthode, ajoutez :

obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = ""

Notez que nous utilisons la référence à l'objet FeaturePython (sérialisable) obj, et non l'instance de classe Python (non sérialisable) self.

Une fois que vous avez terminé, enregistrez les modifications et revenez à FreeCAD. Avant de pouvoir observer les modifications apportées à notre code, nous devons recharger le module. Cela peut être accompli en redémarrant FreeCAD, mais redémarrer FreeCAD à chaque fois que nous éditons le code serait gênant. Pour faciliter les choses, tapez ce qui suit dans la console Python :

from importlib import reload
reload(box)

Avec le module rechargé, voyons ce que nous obtenons lorsque nous créons un objet :

box.create('box_property_test')

Vous devriez voir le nouvel objet boîte apparaître dans l'arborescence :

  • Sélectionnez-le et regardez l'éditeur de propriétés. Là, vous devriez voir la propriété Description.
  • Passez la souris sur le nom de la propriété à gauche et l'info-bulle devrait apparaître avec la description que vous avez fournie.
  • Sélectionnez le champ et tapez ce que vous voulez. Vous remarquerez que les commandes de mise à jour Python sont exécutées et affichées dans la console lorsque vous tapez des lettres et que les propriétés changent.

En haut

Ajoutons quelques propriétés supplémentaires. Retournez à votre code source et ajoutez les propriétés suivantes à la méthode __init__() :

obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = '10 mm'
obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = '1 cm'

Et ajoutons aussi un code pour recalculer le document automatiquement. Ajoutez la ligne suivante au-dessus de l'instruction return() de la méthode create():

App.ActiveDocument.recompute()

Faites attention à l'endroit où vous recalculez un objet FeaturePython. Le recalcul doit être effectué par une méthode externe à sa classe.

Maintenant, testez vos modifications comme suit:

  • Enregistrez vos modifications et rechargez votre module.
  • Supprimez tous les objets dans l'arborescence.
  • Créez un nouvel objet boîte à partir de la console Python en appelant box.create('myBox').

Une fois que la boîte est créée et que vous avez vérifié pour vous assurer qu'elle a été recalculée, sélectionnez l'objet et regardez ses propriétés. Vous devez noter deux choses:

  • Un nouveau groupe de propriétés: Dimensions.
  • Trois nouvelles propriétés: Height, Length et Width.

Notez également que les propriétés ont des unités. Plus précisément, elles ont repris les unités linéaires définies dans les préférences de l'utilisateur (Edition → Préférences... → Général → Unités).

Vous avez sans doute remarqué que trois valeurs différentes ont été saisies pour les dimensions : une valeur en virgule flottante (10.0) et deux chaînes de caractères différentes ('10 mm' et '1 cm'). Le type App::PropertyLength suppose que les valeurs en virgule flottante sont en millimètres, les valeurs des chaînes sont analysées en fonction des unités spécifiées et, dans l'interface graphique, toutes les valeurs sont converties dans les unités spécifiées dans les préférences de l'utilisateur (mm dans l'image). Ce comportement intégré rend le type App::PropertyLength idéal pour les dimensions.

En haut

Piège à événements

Le dernier élément requis pour un objet FeaturePython de base est le recouvrement d'événements. Un objet FeaturePython peut réagir aux événements avec des fonctions de rappel. Dans notre cas, nous voulons que l'objet réagisse chaque fois qu'il est recalculé. En d'autres termes, nous voulons intercepter les recalculs. Pour ce faire, nous devons ajouter une fonction avec un nom spécifique, execute(), à la classe d'objets. Il existe plusieurs autres événements qui peuvent être piégés, à la fois dans l'objet FeaturePython lui-même et dans le ViewProvider, que nous aborderons dans la Création d'une boîte FeaturePython, partie II.

Pour une référence complète des méthodes disponibles à implémenter sur les classes FeautrePython, voir Méthodes FeaturePython.

Ajoutez ce qui suit après la fonction __init__():

def execute(self, obj):
    """
    Called on document recompute
    """

    print('Recomputing {0:s} ({1:s})'.format(obj.Name, self.Type))

Testez le code en suivant à nouveau ces étapes:

  • Enregistrez et rechargez le module.
  • Supprimer tous les objets.
  • Créez un nouvel objet boîte.

Vous devriez voir la sortie imprimée dans la console Python, grâce à l'appel recompute() que nous avons ajouté à la méthode create(). Bien sûr, la méthode execute() ne fait rien ici, sauf nous dire qu'elle a été appelée, mais elle est la clé de la magie des objets FeaturePython.

Voilà, vous savez maintenant comment construire un objet FeaturePython basique et fonctionnel !

En haut

Le code terminé

import FreeCAD as App

def create(obj_name):
    """
    Object creation method
    """

    obj = App.ActiveDocument.addObject('App::FeaturePython', obj_name)

    box(obj)

    App.ActiveDocument.recompute()

    return obj

class box():

    def __init__(self, obj):
        """
        Default constructor
        """

        self.Type = 'box'

        obj.Proxy = self

        obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = ""
        obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
        obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = '10 mm'
        obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = '1 cm'

    def execute(self, obj):
        """
        Called on document recompute
        """

        print('Recomputing {0:s} ({1:s})'.format(obj.Name, self.Type))

En haut