Skip to content
💻 🧠 Code 1001 > 📚 Learning Materials > How to Create Addons for FreeCAD > Lesson 4. Graphical User Interface (GUI): Dialog Box with Input Fields

Lesson 4. Graphical User Interface (GUI): Dialog Box with Input Fields

📘 Tutorial: Creating Addons for FreeCAD

Lesson Goal: Create a window with fields for entering length, width, and height, and build a box with these parameters by clicking a button.


🖼 Part 1. How GUI works in FreeCAD?

FreeCAD uses PySide — a Python wrapper over the Qt library (the same one used in Blender, Maya, and many other programs).

Key components:

  • QtGui.QDialog — modal window
  • QtGui.QLineEdit — text input field
  • QtGui.QPushButton — button
  • QtGui.QFormLayout — convenient “label + field” layout

💡 All GUI elements are created within a Python script, without external files (although you can use .ui from Qt Designer — but we’ll start with something simple).


🛠 Part 2. Addon: “Box Builder with GUI”

We will extend the previous addon by adding a dialog box.

Step 1. Create a folder

.../Mod/BoxBuilderAddon/

Step 2. File InitGui.py

# InitGui.py
import FreeCADGui
from BoxBuilderAddon.box_builder_workbench import BoxBuilderWorkbench

FreeCADGui.addWorkbench(BoxBuilderWorkbench())

Step 3. File box_builder_workbench.py

# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore

# === BOX CREATION FUNCTION ===
def create_box(length, width, height, name="CustomBox"):
    doc = FreeCAD.ActiveDocument
    if not doc:
        doc = FreeCAD.newDocument("BoxBuilder")

    # Unique 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


# === DIALOG WINDOW ===
class BoxBuilderDialog(QtGui.QDialog):
    def __init__(self):
        super(BoxBuilderDialog, self).__init__()
        self.setWindowTitle("Box Builder")
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        self.resize(300, 150)

        # Input fields
        self.length_input = QtGui.QLineEdit("30.0")
        self.width_input = QtGui.QLineEdit("20.0")
        self.height_input = QtGui.QLineEdit("10.0")

        # Buttons
        self.create_button = QtGui.QPushButton("Create Box")
        self.cancel_button = QtGui.QPushButton("Cancel")

        # Connect buttons
        self.create_button.clicked.connect(self.on_create)
        self.cancel_button.clicked.connect(self.reject)

        # 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()  # Close the window

        except ValueError as e:
            QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")


# === COMMAND ===
class BoxBuilderCommand:
    def GetResources(self):
        return {
            "MenuText": "Box Builder",
            "ToolTip": "Create a box with custom dimensions"
        }

    def Activated(self):
        dialog = BoxBuilderDialog()
        dialog.exec_()  # Modal call

    def IsActive(self):
        return True


# === 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())

🔍 Breakdown of Key Parts

1. Dialog Window (BoxBuilderDialog)

  • Inherits from QtGui.QDialog
  • Uses QFormLayout for neat field placement
  • The Create Box button calls on_create(), Cancel — closes the window

2. Input Processing

  • Convert text to float
  • Check that values are positive
  • In case of error — show a warning via QMessageBox.warning

3. Object Creation

  • The create_box() function is separated — for cleaner code
  • Generates a unique name to avoid conflicts

4. Window Launch

  • dialog.exec_() — makes the window modal (you cannot interact with FreeCAD while it is open)

▶️ Step 4. Checking the Operation

  1. Save the files
  2. Restart FreeCAD
  3. Select the «Box Builder» workbench
  4. Click the «Box Builder» button
  5. In the window that appears, enter dimensions → click Create Box

✅ A box with your parameters should appear!

Try:

  • Entering letters → an error will appear
  • Entering a negative number → error
  • Entering fractional numbers (e.g., 12.5) → works!

🧪 Practical Task

  1. Add a fourth field: «Name» — so that the user can set the object’s name.
  2. Make sure that if the name is empty, the default value ("CustomBox") is used.
  3. Add a checkbox «Center on origin» — if enabled, the box should be centered at the origin.

💡 Hint for centering:
After creating the box, change its Placement property:

from FreeCAD import Vector
box.Placement.Base = Vector(-length/2, -width/2, -height/2)

💡 Tips for Working with GUI

  • Always wrap input in try/except — the user can enter anything
  • Use QDoubleValidator to allow only numbers (optional)
  • For complex interfaces, it’s better to use Qt Designer and load .ui files, but for simple tasks — the code is easier

▶️ What’s next?

In Lesson 5 we will:

  • Learn how to save settings between FreeCAD launches
  • Make sure the last entered dimension value is remembered
  • Use FreeCAD’s built-in mechanism: FreeCAD.ParamGet()

This will make your addon even more convenient!

Leave a Reply

Your email address will not be published. Required fields are marked *