Tutorial: Tworzenie Dodatków dla FreeCAD
Cel Lekcji: Stworzenie okna z polami do wprowadzania długości, szerokości i wysokości, a następnie zbudowanie prostopadłościanu z tymi parametrami po kliknięciu przycisku.
W Tym Artykule
- 01 Część 1. Jak działa GUI w FreeCAD?
- 02 Część 2. Dodatek: „Box Builder with GUI” (Kreator Prostopadłościanów z GUI)
- Krok 1. Utwórz folder
- Krok 2. Plik InitGui.py
- Krok 3. Plik box_builder_workbench.py
- Rozbicie Kluczowych Części
- Okno Dialogowe ($\text{BoxBuilderDialog}$)
- Przetwarzanie Wejścia
- Tworzenie Obiektu
- Uruchomienie Okna
- Rozbicie Kluczowych Części
- 04 Krok 4. Sprawdzenie Działania
- 05 Zadanie Praktyczne
- 06 Wskazówki do Pracy z GUI
- 07 Co dalej?
Część 1. Jak działa GUI w FreeCAD?
FreeCAD używa $\text{PySide}$ – wrappera Pythona dla biblioteki Qt (tej samej, której używają Blender, Maya i wiele innych programów).
Kluczowe komponenty:
- $\text{QtGui.QDialog}$ – okno modalne
- $\text{QtGui.QLineEdit}$ – pole do wprowadzania tekstu
- $\text{QtGui.QPushButton}$ – przycisk
- $\text{QtGui.QFormLayout}$ – wygodny układ „etykieta + pole”
Wszystkie elementy GUI są tworzone wewnątrz skryptu Pythona, bez plików zewnętrznych (chociaż można użyć $\text{ui}$ z $\text{Qt Designer}$ – ale zaczniemy od czegoś prostego).
Część 2. Dodatek: „Box Builder with GUI”
Rozszerzymy poprzedni dodatek, dodając okno dialogowe.
Krok 1. Utwórz folder
$\text{…/Mod/BoxBuilderAddon/}$
Krok 2. Plik InitGui.py
Python
# InitGui.py
import FreeCADGui
from BoxBuilderAddon.box_builder_workbench import BoxBuilderWorkbench
FreeCADGui.addWorkbench(BoxBuilderWorkbench())
Krok 3. Plik box_builder_workbench.py
Python
# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore
# === FUNKCJA TWORZENIA PROSTOPADŁOŚCIANU ===
def create_box(length, width, height, name="CustomBox"):
doc = FreeCAD.ActiveDocument
if not doc:
doc = FreeCAD.newDocument("BoxBuilder")
# Unikalna nazwa
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
# === OKNO DIALOGOWE ===
class BoxBuilderDialog(QtGui.QDialog):
def __init__(self):
super(BoxBuilderDialog, self).__init__()
self.setWindowTitle("Box Builder")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.resize(300, 150)
# Pola wejściowe
self.length_input = QtGui.QLineEdit("30.0")
self.width_input = QtGui.QLineEdit("20.0")
self.height_input = QtGui.QLineEdit("10.0")
# Przyciski
self.create_button = QtGui.QPushButton("Create Box")
self.cancel_button = QtGui.QPushButton("Cancel")
# Łączenie przycisków
self.create_button.clicked.connect(self.on_create)
self.cancel_button.clicked.connect(self.reject)
# Układ (Layout)
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() # Zamknij okno
except ValueError as e:
QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")
# === KOMENDA ===
class BoxBuilderCommand:
def GetResources(self):
return {
"MenuText": "Box Builder",
"ToolTip": "Create a box with custom dimensions"
}
def Activated(self):
dialog = BoxBuilderDialog()
dialog.exec_() # Wywołanie modalne
def IsActive(self):
return True
# === ŚRODOWISKO PRACY (WORKBENCH) ===
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())
Rozbicie Kluczowych Części
- Okno Dialogowe ($\text{BoxBuilderDialog}$)
- Dziedziczy z $\text{QtGui.QDialog}$
- Używa $\text{QFormLayout}$ do uporządkowanego umieszczania pól
- Przycisk „Create Box” wywołuje $\text{on\_create()}$, „Cancel” zamyka okno
- Przetwarzanie Wejścia
- Konwertuje tekst na liczbę zmiennoprzecinkową ($\text{float}$)
- Sprawdza, czy wartości są dodatnie
- W przypadku błędu wyświetla ostrzeżenie za pomocą $\text{QMessageBox.warning}$
- Tworzenie Obiektu
- Funkcja $\text{create\_box()}$ jest wydzielona dla czystszego kodu
- Generuje unikalną nazwę, aby uniknąć konfliktów
- Uruchomienie Okna
- $\text{dialog.exec\_()}$ sprawia, że okno jest modalne (nie można wchodzić w interakcję z FreeCAD, gdy jest otwarte)
Krok 4. Sprawdzenie Działania
- Zapisz pliki
- Uruchom ponownie FreeCAD
- Wybierz środowisko pracy „Box Builder„
- Kliknij przycisk „Box Builder„
- W oknie, które się pojawi, wprowadź wymiary $\rightarrow$ kliknij $\text{Create Box}$
- Powinien pojawić się prostopadłościan z Twoimi parametrami!
Wypróbuj:
- Wprowadzenie liter $\rightarrow$ pojawi się błąd
- Wprowadzenie liczby ujemnej $\rightarrow$ błąd
- Wprowadzenie liczb ułamkowych (np. 12.5) działa!
Zadanie Praktyczne
- Dodaj czwarte pole: „Nazwa” – aby użytkownik mógł ustawić nazwę obiektu.
- Upewnij się, że jeśli nazwa jest pusta, zostanie użyta domyślna wartość („$\text{CustomBox}$”).
- Dodaj pole wyboru ($\text{checkbox}$) „Center on origin” (Wyśrodkuj na początku układu współrzędnych) $\rightarrow$ jeśli jest włączone, prostopadłościan powinien być wyśrodkowany.
Wskazówka do centrowania:
Po utworzeniu prostopadłościanu zmień jego właściwość $\text{Placement}$:
Python
from FreeCAD import Vector
box.Placement.Base = Vector(-length/2, -width/2, height/2)
Wskazówki do Pracy z GUI
- Zawsze owijaj wprowadzanie danych w $\text{try/except}$ $\rightarrow$ użytkownik może wprowadzić cokolwiek
- Użyj $\text{QDoubleValidator}$, aby zezwolić tylko na liczby (opcjonalnie)
- Dla bardziej złożonych interfejsów lepiej jest użyć $\text{Qt Designer}$ i ładować pliki $\text{.ui}$, ale dla prostych zadań kod jest łatwiejszy
Co dalej?
W Lekcji 5 nauczymy się:
- Jak zapisywać ustawienia pomiędzy uruchomieniami FreeCAD
- Zapewnić zapamiętanie ostatnio wprowadzonej wartości wymiaru
- Użyć wbudowanego mechanizmu FreeCAD: $\text{FreeCAD.ParamGet()}$
- To sprawi, że Twój dodatek będzie jeszcze wygodniejszy!