📘 Corso di formazione: Creazione di addon per FreeCAD
Obiettivo della lezione: fare in modo che l’addon «Box Builder» memorizzi le ultime dimensioni inserite e le ripristini al successivo avvio.
💾 Parte 1. Come FreeCAD memorizza le impostazioni?
FreeCAD fornisce un meccanismo integrato per la memorizzazione dei parametri utente — tramite il Parameter Manager.
Funziona con una base di parametri gerarchica, simile al Registro di Windows.
Metodi principali:
# Ottieni un gruppo di parametri
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/MyAddon")
# Salva un valore
params.SetFloat("LastLength", 30.0)
params.SetString("LastName", "MyBox")
# Carica un valore (con un valore predefinito)
length = params.GetFloat("LastLength", 10.0) # 10.0 — se il parametro non esiste
name = params.GetString("LastName", "DefaultBox")
💡 Il percorso
"User parameter:BaseApp/Preferences/..."— è il luogo standard per le impostazioni utente.
🛠 Parte 2. Addon aggiornato: «Box Builder con memoria»
Modificheremo l’addon precedente, aggiungendo il salvataggio e il caricamento degli ultimi valori.
File box_builder_workbench.py (versione aggiornata)
# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore
# === PERCORSO DELLE IMPOSTAZIONI ===
PARAM_PATH = "User parameter:BaseApp/Preferences/BoxBuilderAddon"
def get_saved_settings():
"""Carica le impostazioni salvate o restituisce i valori predefiniti"""
params = FreeCAD.ParamGet(PARAM_PATH)
return {
"length": params.GetFloat("LastLength", 30.0),
"width": params.GetFloat("LastWidth", 20.0),
"height": params.GetFloat("LastHeight", 10.0),
"name": params.GetString("LastName", "CustomBox")
}
def save_settings(length, width, height, name):
"""Salva le impostazioni attuali"""
params = FreeCAD.ParamGet(PARAM_PATH)
params.SetFloat("LastLength", length)
params.SetFloat("LastWidth", width)
params.SetFloat("LastHeight", height)
params.SetString("LastName", name)
# === FUNZIONE DI CREAZIONE SCATOLA ===
def create_box(length, width, height, name="CustomBox"):
doc = FreeCAD.ActiveDocument
if not doc:
doc = FreeCAD.newDocument("BoxBuilder")
# Nome unico
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
# === FINESTRA DI DIALOGO ===
class BoxBuilderDialog(QtGui.QDialog):
def __init__(self):
super(BoxBuilderDialog, self).__init__()
self.setWindowTitle("Box Builder")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.resize(300, 180)
# Carica le impostazioni salvate
settings = get_saved_settings()
# Campi di input
self.length_input = QtGui.QLineEdit(str(settings["length"]))
self.width_input = QtGui.QLineEdit(str(settings["width"]))
self.height_input = QtGui.QLineEdit(str(settings["height"]))
self.name_input = QtGui.QLineEdit(settings["name"])
# Pulsanti
self.create_button = QtGui.QPushButton("Create Box")
self.cancel_button = QtGui.QPushButton("Cancel")
# Connessione
self.create_button.clicked.connect(self.on_create)
self.cancel_button.clicked.connect(self.reject)
# Layout
layout = QtGui.QFormLayout()
layout.addRow("Name:", self.name_input)
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:
name = self.name_input.text().strip()
if not name:
name = "CustomBox"
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")
# Crea l'oggetto
create_box(length, width, height, name)
# Salva le impostazioni
save_settings(length, width, height, name)
self.accept()
except ValueError as e:
QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")
# === COMANDO E AMBIENTE DI LAVORO (senza modifiche) ===
class BoxBuilderCommand:
def GetResources(self):
return {"MenuText": "Box Builder", "ToolTip": "Create a box with custom dimensions"}
def Activated(self):
dialog = BoxBuilderDialog()
dialog.exec_()
def IsActive(self):
return True
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())
🔍 Cosa è cambiato?
- Funzioni aggiunte:
get_saved_settings()— carica gli ultimi valorisave_settings()— salva i valori attuali
- Percorso dei parametri:
PARAM_PATH = "User parameter:BaseApp/Preferences/BoxBuilderAddon"
→ Tutte le impostazioni sono memorizzate in un gruppo separato, senza interferire con altri addon.
- Campo per il nome aggiunto all’interfaccia.
- All’avvio della finestra — i campi vengono popolati con i valori salvati.
- Dopo la creazione — i valori attuali vengono salvati automaticamente.
▶️ Verifica del funzionamento
- Avvia FreeCAD
- Apri Box Builder
- Inserisci, ad esempio:
- Name:
MyTestBox - Length:
50 - Width:
30 - Height:
20
- Clicca su Create Box
- Chiudi FreeCAD
- Avvia di nuovo
- Apri Box Builder
✅ I campi dovrebbero essere popolati con gli stessi valori!
📂 Dove sono memorizzate queste impostazioni?
- Windows: nel registro (
HKEY_CURRENT_USER\SOFTWARE\FreeCAD\...) - Linux/macOS: nel file
user.cfgall’interno della cartella FreeCAD
Ma non è necessario saperlo — FreeCAD gestisce autonomamente la memorizzazione.
🧪 Esercizio pratico
- Aggiungi la casella di controllo «Center on origin» e salva il suo stato tra gli avvii.
- Fai in modo che al primo avvio dell’addon vengano utilizzati valori predefiniti ragionevoli (già implementato).
- Aggiungi un pulsante «Reset to defaults», che ripristina i campi ai valori predefiniti e cancella le impostazioni salvate.
Suggerimento per il ripristino:
def reset_settings():
params = FreeCAD.ParamGet(PARAM_PATH)
params.RemGroup("BoxBuilderAddon") # Rimuove l'intero gruppo
💡 Consigli
- Specifica sempre un valore predefinito in
GetFloat(),GetString()ecc. - Non salvare troppo — solo ciò che è realmente necessario all’utente
- Usa un percorso unico (
BoxBuilderAddon) per non entrare in conflitto con altri addon
▶️ Cosa c’è dopo?
Nella Lezione 6 impareremo a:
- Aggiungere icone ai pulsanti e all’ambiente di lavoro
- Utilizzare SVG e PNG nell’interfaccia
- Rendere l’addon visivamente accattivante