📘 Curso: Creación de complementos para FreeCAD
Objetivo de la lección: crear una ventana con campos para introducir la longitud, la anchura y la altura, y al pulsar un botón construir una caja con esos parámetros.
🖼 Parte 1. ¿Cómo funciona la GUI en FreeCAD?
FreeCAD utiliza PySide, un envoltorio de Python sobre la biblioteca Qt (la misma que se usa en Blender, Maya y muchos otros programas).
Componentes principales:
QtGui.QDialog— ventana modalQtGui.QLineEdit— campo de entrada de textoQtGui.QPushButton— botónQtGui.QFormLayout— diseño cómodo de «etiqueta + campo»
💡 Todos los elementos de la GUI se crean dentro del script de Python, sin archivos externos (aunque se puede usar
.uide Qt Designer, pero empezaremos con algo sencillo).
🛠 Parte 2. Complemento: «Box Builder con GUI»
Ampliaremos el complemento anterior añadiendo un cuadro de diálogo.
Paso 1. Crea una carpeta
.../Mod/BoxBuilderAddon/
Paso 2. Archivo InitGui.py
# InitGui.py
import FreeCADGui
from BoxBuilderAddon.box_builder_workbench import BoxBuilderWorkbench
FreeCADGui.addWorkbench(BoxBuilderWorkbench())
Paso 3. Archivo box_builder_workbench.py
# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore
# === FUNCIÓN DE CREACIÓN DE CAJA ===
def create_box(length, width, height, name="CustomBox"):
doc = FreeCAD.ActiveDocument
if not doc:
doc = FreeCAD.newDocument("BoxBuilder")
# Nombre único
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
# === CUADRO DE DIÁLOGO ===
class BoxBuilderDialog(QtGui.QDialog):
def __init__(self):
super(BoxBuilderDialog, self).__init__()
self.setWindowTitle("Box Builder")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.resize(300, 150)
# Campos de entrada
self.length_input = QtGui.QLineEdit("30.0")
self.width_input = QtGui.QLineEdit("20.0")
self.height_input = QtGui.QLineEdit("10.0")
# Botones
self.create_button = QtGui.QPushButton("Create Box")
self.cancel_button = QtGui.QPushButton("Cancel")
# Conexión de botones
self.create_button.clicked.connect(self.on_create)
self.cancel_button.clicked.connect(self.reject)
# Diseño
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() # Cerrar ventana
except ValueError as e:
QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")
# === COMANDO ===
class BoxBuilderCommand:
def GetResources(self):
return {
"MenuText": "Box Builder",
"ToolTip": "Create a box with custom dimensions"
}
def Activated(self):
dialog = BoxBuilderDialog()
dialog.exec_() # Llamada modal
def IsActive(self):
return True
# === ENTORNO DE TRABAJO ===
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())
🔍 Desglose de las partes clave
1. Cuadro de diálogo (BoxBuilderDialog)
- Hereda de
QtGui.QDialog - Utiliza
QFormLayoutpara una colocación ordenada de los campos - El botón Create Box llama a
on_create(), Cancel — cierra la ventana
2. Procesamiento de la entrada
- Convertimos el texto a
float - Comprobamos que los valores sean positivos
- En caso de error — mostramos una advertencia a través de
QMessageBox.warning
3. Creación del objeto
- La función
create_box()se ha extraído por separado — para un código más limpio - Genera un nombre único para evitar conflictos
4. Lanzamiento de la ventana
dialog.exec_()— hace que la ventana sea modal (no se puede interactuar con FreeCAD mientras esté abierta)
▶️ Paso 4. Comprobación del funcionamiento
- Guarda los archivos
- Reinicia FreeCAD
- Selecciona el entorno de trabajo «Box Builder»
- Haz clic en el botón «Box Builder»
- En la ventana que aparece, introduce las dimensiones → haz clic en Create Box
✅ ¡Debería aparecer una caja con tus parámetros!
Prueba a:
- Introducir letras → aparecerá un error
- Introducir un número negativo → error
- Introducir números decimales (por ejemplo,
12.5) → ¡funciona!
🧪 Tarea práctica
- Añade un cuarto campo: «Name» — para que el usuario pueda establecer el nombre del objeto.
- Haz que si el nombre está vacío, se utilice el valor predeterminado (
"CustomBox"). - Añade una casilla de verificación «Center on origin» — si está activada, la caja debe estar centrada en el origen.
💡 Sugerencia para centrar:
Después de crear la caja, cambia su propiedadPlacement:from FreeCAD import Vector box.Placement.Base = Vector(-length/2, -width/2, -height/2)
💡 Consejos para trabajar con la GUI
- Envuelve siempre la entrada en
try/except— el usuario puede introducir cualquier cosa - Utiliza
QDoubleValidatorpara permitir solo números (opcional) - Para interfaces complejas, es mejor usar Qt Designer y cargar archivos
.ui, pero para tareas sencillas — el código es más fácil
▶️ ¿Qué sigue?
En la Lección 5 aprenderemos a:
- Guardar configuraciones entre inicios de FreeCAD
- Hacer que el último valor de las dimensiones introducidas se recuerde
- Utilizar el mecanismo integrado de FreeCAD:
FreeCAD.ParamGet()
¡Esto hará que tu complemento sea aún más cómodo!