Lernziel: Erstelle ein Fenster mit Feldern zur Eingabe von Länge, Breite und Höhe und baue durch Klick auf eine Schaltfläche eine Box mit diesen Parametern.
Teil 1. Wie funktioniert die GUI in FreeCAD?
FreeCAD verwendet PySide – einen Python-Wrapper für die Qt-Bibliothek (dieselbe, die auch in Blender, Maya und vielen anderen Programmen verwendet wird).
Wichtige Komponenten:
QtGui.QDialog— modales FensterQtGui.QLineEdit— TexteingabefeldQtGui.QPushButton— SchaltflächeQtGui.QFormLayout— praktisches Layout für „Beschriftung + Feld“
Alle GUI-Elemente werden innerhalb eines Python-Skripts erstellt – ohne externe Dateien (obwohl man auch .ui-Dateien aus Qt Designer nutzen kann; wir beginnen jedoch mit etwas Einfachem).
Teil 2. Addon: „Box Builder mit GUI“
Wir erweitern das vorherige Addon um ein Dialogfenster.
Schritt 1. Ordner erstellen
.../Mod/BoxBuilderAddon/
Schritt 2. Datei InitGui.py
# InitGui.py
import FreeCADGui
from BoxBuilderAddon.box_builder_workbench import BoxBuilderWorkbench
FreeCADGui.addWorkbench(BoxBuilderWorkbench())
Schritt 3. Datei box_builder_workbench.py
# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore
# === BOX-ERSTELLUNGSFUNKTION ===
def create_box(length, width, height, name="CustomBox"):
doc = FreeCAD.ActiveDocument
if not doc:
doc = FreeCAD.newDocument("BoxBuilder")
# Eindeutiger Name
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
# === DIALOGFENSTER ===
class BoxBuilderDialog(QtGui.QDialog):
def __init__(self):
super(BoxBuilderDialog, self).__init__()
self.setWindowTitle("Box Builder")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.resize(300, 150)
# Eingabefelder
self.length_input = QtGui.QLineEdit("30.0")
self.width_input = QtGui.QLineEdit("20.0")
self.height_input = QtGui.QLineEdit("10.0")
# Schaltflächen
self.create_button = QtGui.QPushButton("Box erstellen")
self.cancel_button = QtGui.QPushButton("Abbrechen")
# Schaltflächen verbinden
self.create_button.clicked.connect(self.on_create)
self.cancel_button.clicked.connect(self.reject)
# Layout
layout = QtGui.QFormLayout()
layout.addRow("Länge (mm):", self.length_input)
layout.addRow("Breite (mm):", self.width_input)
layout.addRow("Höhe (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("Alle Abmessungen müssen positiv sein")
create_box(length, width, height)
self.accept() # Fenster schließen
except ValueError as e:
QtGui.QMessageBox.warning(self, "Eingabefehler", f"Ungültige Eingabe:\n{str(e)}")
# === BEFEHL ===
class BoxBuilderCommand:
def GetResources(self):
return {
"MenuText": "Box Builder",
"ToolTip": "Erstelle eine Box mit benutzerdefinierten Abmessungen"
}
def Activated(self):
dialog = BoxBuilderDialog()
dialog.exec_() # Modaler Aufruf
def IsActive(self):
return True
# === ARBEITSUMGEBUNG ===
class BoxBuilderWorkbench(FreeCADGui.Workbench):
MenuText = "Box Builder"
ToolTip = "Erstelle benutzerdefinierte Boxen mit grafischer Oberfläche"
def Initialize(self):
self.list = ["BoxBuilderCommand"]
self.appendToolbar("Box-Werkzeuge", self.list)
self.appendMenu("Box Builder", self.list)
def GetClassName(self):
return "Gui::PythonWorkbench"
FreeCADGui.addCommand("BoxBuilderCommand", BoxBuilderCommand())
Analyse der wichtigsten Teile
- Dialogfenster (
BoxBuilderDialog)
- Erbt von
QtGui.QDialog - Verwendet
QFormLayoutfür eine übersichtliche Anordnung der Felder - Die Schaltfläche „Box erstellen“ ruft
on_create()auf, „Abbrechen“ schließt das Fenster
- Eingabeverarbeitung
- Wandelt Text in
floatum - Prüft, ob Werte positiv sind
- Bei Fehlern wird eine Warnung über
QMessageBox.warningangezeigt
- Objekterstellung
- Die Funktion
create_box()ist separat – für übersichtlicheren Code - Generiert einen eindeutigen Namen, um Konflikte zu vermeiden
- Fensterstart
dialog.exec_()macht das Fenster modal (man kann FreeCAD nicht bedienen, solange es geöffnet ist)
Schritt 4. Funktionsprüfung
- Speichere die Dateien
- Starte FreeCAD neu
- Wähle die Arbeitsumgebung „Box Builder“ aus
- Klicke auf die Schaltfläche „Box Builder“
- Gib im erscheinenden Fenster Abmessungen ein → klicke auf „Box erstellen“
Es sollte eine Box mit deinen Parametern erscheinen!
Probiere aus:
- Buchstaben eingeben → Fehlermeldung erscheint
- Negative Zahl eingeben → Fehler
- Dezimalzahlen (z. B. 12,5) eingeben → funktioniert!
Praktische Aufgabe
- Füge ein viertes Feld „Name“ hinzu – damit der Benutzer den Objektnamen festlegen kann.
- Stelle sicher, dass bei leerem Namen der Standardwert (
"CustomBox") verwendet wird. - Füge ein Kontrollkästchen „Am Ursprung zentrieren“ hinzu – wenn aktiviert, soll die Box am Ursprung zentriert werden.
Hinweis zur Zentrierung:
Nach der Erstellung der Box die Placement-Eigenschaft ändern:
from FreeCAD import Vector
box.Placement.Base = Vector(-length/2, -width/2, -height/2)
Tipps zur Arbeit mit der GUI
- Umschließe Eingaben immer mit
try/except– der Benutzer kann alles Mögliche eingeben - Verwende optional
QDoubleValidator, um nur Zahlen zuzulassen - Für komplexe Oberflächen ist es besser, Qt Designer zu nutzen und
.ui-Dateien zu laden – für einfache Aufgaben reicht jedoch Code
Was kommt als Nächstes?
In Lektion 5 werden wir:
- Lernen, wie man Einstellungen zwischen FreeCAD-Sitzungen speichert
- Sicherstellen, dass der zuletzt eingegebene Wert gemerkt wird
- Den integrierten Mechanismus von FreeCAD nutzen:
FreeCAD.ParamGet()
Damit wird dein Addon noch komfortabler!