📘 Учебный курс: Создание аддонов для FreeCAD
Цель урока: создать окно с полями для ввода длины, ширины и высоты, и по нажатию кнопки строить коробку с этими параметрами.
In Questo Articolo
🖼 Часть 1. Как работает GUI в FreeCAD?
FreeCAD использует PySide — Python-обёртку над библиотекой Qt (та же, что в Blender, Maya, и многих других программах).
Основные компоненты:
QtGui.QDialog— модальное окноQtGui.QLineEdit— поле ввода текстаQtGui.QPushButton— кнопкаQtGui.QFormLayout— удобная раскладка «метка + поле»
💡 Все GUI-элементы создаются внутри Python-скрипта, без внешних файлов (хотя можно использовать
.uiиз Qt Designer — но мы начнём с простого).
🛠 Часть 2. Аддон: «Box Builder с GUI»
Мы расширим предыдущий аддон, добавив диалоговое окно.
Шаг 1. Создайте папку
.../Mod/BoxBuilderAddon/
Шаг 2. Файл InitGui.py
# InitGui.py
import FreeCADGui
from BoxBuilderAddon.box_builder_workbench import BoxBuilderWorkbench
FreeCADGui.addWorkbench(BoxBuilderWorkbench())
Шаг 3. Файл box_builder_workbench.py
# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore
# === ФУНКЦИЯ СОЗДАНИЯ КОРОБКИ ===
def create_box(length, width, height, name="CustomBox"):
doc = FreeCAD.ActiveDocument
if not doc:
doc = FreeCAD.newDocument("BoxBuilder")
# Уникальное имя
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
# === ДИАЛОГОВОЕ ОКНО ===
class BoxBuilderDialog(QtGui.QDialog):
def __init__(self):
super(BoxBuilderDialog, self).__init__()
self.setWindowTitle("Box Builder")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.resize(300, 150)
# Поля ввода
self.length_input = QtGui.QLineEdit("30.0")
self.width_input = QtGui.QLineEdit("20.0")
self.height_input = QtGui.QLineEdit("10.0")
# Кнопки
self.create_button = QtGui.QPushButton("Create Box")
self.cancel_button = QtGui.QPushButton("Cancel")
# Подключение кнопок
self.create_button.clicked.connect(self.on_create)
self.cancel_button.clicked.connect(self.reject)
# Раскладка
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() # Закрываем окно
except ValueError as e:
QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")
# === КОМАНДА ===
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())
🔍 Разбор ключевых частей
1. Диалоговое окно (BoxBuilderDialog)
- Наследуется от
QtGui.QDialog - Использует
QFormLayoutдля аккуратного размещения полей - Кнопка Create Box вызывает
on_create(), Cancel — закрывает окно
2. Обработка ввода
- Преобразуем текст в
float - Проверяем, что значения положительные
- При ошибке — показываем предупреждение через
QMessageBox.warning
3. Создание объекта
- Функция
create_box()вынесена отдельно — так код чище - Генерирует уникальное имя, чтобы не было конфликтов
4. Запуск окна
dialog.exec_()— делает окно модальным (нельзя взаимодействовать с FreeCAD, пока оно открыто)
▶️ Шаг 4. Проверка работы
- Сохраните файлы
- Перезапустите FreeCAD
- Выберите рабочую среду «Box Builder»
- Нажмите кнопку «Box Builder»
- В появившемся окне введите размеры → нажмите Create Box
✅ Должна появиться коробка с вашими параметрами!
Попробуйте:
- Ввести буквы → появится ошибка
- Ввести отрицательное число → ошибка
- Ввести дробные числа (например,
12.5) → работает!
🧪 Практическое задание
- Добавьте четвёртое поле: «Name» — чтобы пользователь мог задать имя объекта.
- Сделайте так, чтобы при пустом имени использовалось значение по умолчанию (
"CustomBox"). - Добавьте галочку «Center on origin» — если включена, коробка должна быть центрирована в начале координат.
💡 Подсказка для центрирования:
После создания коробки измените её свойствоPlacement:from FreeCAD import Vector box.Placement.Base = Vector(-length/2, -width/2, -height/2)
💡 Советы по работе с GUI
- Всегда оборачивайте ввод в
try/except— пользователь может ввести что угодно - Используйте
QDoubleValidator, чтобы разрешить только числа (опционально) - Для сложных интерфейсов лучше использовать Qt Designer и загружать
.ui-файлы, но для простых задач — код проще
▶️ Что дальше?
В Уроке 5 мы:
- Научимся сохранять настройки между запусками FreeCAD
- Сделаем так, чтобы последнее введённое значение размеров запоминалось
- Используем встроенный механизм FreeCAD:
FreeCAD.ParamGet()
Это сделает ваш аддон ещё удобнее!