Aller au contenu
> 💻 🧠 Code 1001 > 📖 Guides > Création de modules complémentaires pour FreeCAD > Leçon 4. Interface graphique (GUI) : boîte de dialogue avec champs de saisie

Leçon 4. Interface graphique (GUI) : boîte de dialogue avec champs de saisie

  • par

📘 Cours : Création d’add-ons pour FreeCAD

Objectif de la leçon : créer une fenêtre avec des champs pour saisir la longueur, la largeur et la hauteur, et construire une boîte avec ces paramètres en cliquant sur un bouton.


🖼 Partie 1. Comment fonctionne la GUI dans FreeCAD ?

FreeCAD utilise PySide — un wrapper Python sur la bibliothèque Qt (la même que dans Blender, Maya et de nombreux autres programmes).

Composants principaux :

  • QtGui.QDialog — fenêtre modale
  • QtGui.QLineEdit — champ de saisie de texte
  • QtGui.QPushButton — bouton
  • QtGui.QFormLayout — disposition pratique « étiquette + champ »

💡 Tous les éléments de la GUI sont créés à l’intérieur du script Python, sans fichiers externes (bien que l’on puisse utiliser .ui de Qt Designer — mais nous commencerons par le plus simple).


🛠 Partie 2. Add-on : « Box Builder avec GUI »

Nous allons étendre l’add-on précédent en ajoutant une boîte de dialogue.

Étape 1. Créez un dossier

.../Mod/BoxBuilderAddon/

Étape 2. Fichier InitGui.py

# InitGui.py
import FreeCADGui
from BoxBuilderAddon.box_builder_workbench import BoxBuilderWorkbench

FreeCADGui.addWorkbench(BoxBuilderWorkbench())

Étape 3. Fichier box_builder_workbench.py

# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore

# === FONCTION DE CRÉATION DE BOÎTE ===
def create_box(length, width, height, name="CustomBox"):
    doc = FreeCAD.ActiveDocument
    if not doc:
        doc = FreeCAD.newDocument("BoxBuilder")

    # Nom unique
    base_name = name
    index = 1
    obj_name = base_name
    while obj_name in [obj.Name for obj in doc.Objects]:
        obj_name = f"{base_name}_{index}"
        index += 1

    box = doc.addObject("Part::Box", obj_name)
    box.Length = length
    box.Width = width
    box.Height = height
    doc.recompute()
    return box


# === FENÊTRE DE DIALOGUE ===
class BoxBuilderDialog(QtGui.QDialog):
    def __init__(self):
        super(BoxBuilderDialog, self).__init__()
        self.setWindowTitle("Box Builder")
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        self.resize(300, 150)

        # Champs de saisie
        self.length_input = QtGui.QLineEdit("30.0")
        self.width_input = QtGui.QLineEdit("20.0")
        self.height_input = QtGui.QLineEdit("10.0")

        # Boutons
        self.create_button = QtGui.QPushButton("Create Box")
        self.cancel_button = QtGui.QPushButton("Cancel")

        # Connexion des boutons
        self.create_button.clicked.connect(self.on_create)
        self.cancel_button.clicked.connect(self.reject)

        # Disposition
        layout = QtGui.QFormLayout()
        layout.addRow("Length (mm):", self.length_input)
        layout.addRow("Width (mm):", self.width_input)
        layout.addRow("Height (mm):", self.height_input)

        button_layout = QtGui.QHBoxLayout()
        button_layout.addWidget(self.create_button)
        button_layout.addWidget(self.cancel_button)

        main_layout = QtGui.QVBoxLayout()
        main_layout.addLayout(layout)
        main_layout.addLayout(button_layout)
        self.setLayout(main_layout)

    def on_create(self):
        try:
            length = float(self.length_input.text())
            width = float(self.width_input.text())
            height = float(self.height_input.text())

            if length <= 0 or width <= 0 or height <= 0:
                raise ValueError("All dimensions must be positive")

            create_box(length, width, height)
            self.accept()  # Fermer la fenêtre

        except ValueError as e:
            QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")


# === COMMANDE ===
class BoxBuilderCommand:
    def GetResources(self):
        return {
            "MenuText": "Box Builder",
            "ToolTip": "Create a box with custom dimensions"
        }

    def Activated(self):
        dialog = BoxBuilderDialog()
        dialog.exec_()  # Appel modal

    def IsActive(self):
        return True


# === ENVIRONNEMENT DE TRAVAIL ===
class BoxBuilderWorkbench(FreeCADGui.Workbench):
    MenuText = "Box Builder"
    ToolTip = "Create custom boxes with GUI"

    def Initialize(self):
        self.list = ["BoxBuilderCommand"]
        self.appendToolbar("Box Tools", self.list)
        self.appendMenu("Box Builder", self.list)

    def GetClassName(self):
        return "Gui::PythonWorkbench"


FreeCADGui.addCommand("BoxBuilderCommand", BoxBuilderCommand())

🔍 Analyse des parties clés

1. Fenêtre de dialogue (BoxBuilderDialog)

  • Hérite de QtGui.QDialog
  • Utilise QFormLayout pour un placement soigné des champs
  • Le bouton Create Box appelle on_create(), Cancel — ferme la fenêtre

2. Traitement de la saisie

  • Convertit le texte en float
  • Vérifie que les valeurs sont positives
  • En cas d’erreur — affiche un avertissement via QMessageBox.warning

3. Création de l’objet

  • La fonction create_box() est séparée — pour un code plus propre
  • Génère un nom unique pour éviter les conflits

4. Lancement de la fenêtre

  • dialog.exec_() — rend la fenêtre modale (vous ne pouvez pas interagir avec FreeCAD tant qu’elle est ouverte)

▶️ Étape 4. Vérification du fonctionnement

  1. Enregistrez les fichiers
  2. Redémarrez FreeCAD
  3. Sélectionnez l’environnement de travail « Box Builder »
  4. Cliquez sur le bouton « Box Builder »
  5. Dans la fenêtre qui apparaît, saisissez les dimensions → cliquez sur Create Box

✅ Une boîte avec vos paramètres devrait apparaître !

Essayez :

  • De saisir des lettres → une erreur apparaîtra
  • De saisir un nombre négatif → erreur
  • De saisir des nombres décimaux (par exemple, 12.5) → cela fonctionne !

🧪 Exercice pratique

  1. Ajoutez un quatrième champ : « Name » — pour que l’utilisateur puisse définir le nom de l’objet.
  2. Faites en sorte que si le nom est vide, la valeur par défaut ("CustomBox") soit utilisée.
  3. Ajoutez une case à cocher « Center on origin » — si elle est activée, la boîte doit être centrée à l’origine.

💡 Indice pour le centrage :
Après avoir créé la boîte, modifiez sa propriété Placement :

from FreeCAD import Vector
box.Placement.Base = Vector(-length/2, -width/2, -height/2)

💡 Conseils pour travailler avec la GUI

  • Enveloppez toujours la saisie dans try/except — l’utilisateur peut saisir n’importe quoi
  • Utilisez QDoubleValidator pour n’autoriser que les nombres (facultatif)
  • Pour les interfaces complexes, il est préférable d’utiliser Qt Designer et de charger des fichiers .ui, mais pour les tâches simples — le code est plus facile

▶️ Et ensuite ?

Dans la Leçon 5, nous allons :

  • Apprendre à enregistrer les paramètres entre les démarrages de FreeCAD
  • Faire en sorte que la dernière valeur de dimension saisie soit mémorisée
  • Utiliser le mécanisme intégré de FreeCAD : FreeCAD.ParamGet()

Cela rendra votre add-on encore plus pratique !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *