Перейти к содержимому
davidka.net > 💻 🧠 Код 1001 > 📚 Учебные Материалы > FreeCAD > Создание аддонов для FreeCAD > Урок 4. Графический интерфейс (GUI): диалоговое окно с полями ввода

Урок 4. Графический интерфейс (GUI): диалоговое окно с полями ввода

  • автор:

📘 Учебный курс: Создание аддонов для FreeCAD

Цель урока: создать окно с полями для ввода длины, ширины и высоты, и по нажатию кнопки строить коробку с этими параметрами.


🖼 Часть 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. Проверка работы

  1. Сохраните файлы
  2. Перезапустите FreeCAD
  3. Выберите рабочую среду «Box Builder»
  4. Нажмите кнопку «Box Builder»
  5. В появившемся окне введите размеры → нажмите Create Box

✅ Должна появиться коробка с вашими параметрами!

Попробуйте:

  • Ввести буквы → появится ошибка
  • Ввести отрицательное число → ошибка
  • Ввести дробные числа (например, 12.5) → работает!

🧪 Практическое задание

  1. Добавьте четвёртое поле: «Name» — чтобы пользователь мог задать имя объекта.
  2. Сделайте так, чтобы при пустом имени использовалось значение по умолчанию ("CustomBox").
  3. Добавьте галочку «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()

Это сделает ваш аддон ещё удобнее!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *