Add Custom UI Dialogs and Buttons to FreeCAD
Extending FreeCAD with custom user interface elements allows users and developers to automate workflows, solicit user input, and streamline complex modeling tasks. This guide explains how to build custom user interface dialogs using Python and PySide (Qt) and how to integrate them into FreeCAD as clickable toolbar buttons using FreeCAD’s native command architecture.
Understanding the Architecture
FreeCAD's graphical interface is built on the Qt framework, exposed
to Python through the PySide library (PySide2 in FreeCAD
0.19–0.21, and transitioning to PySide6 in FreeCAD
1.0).
Adding custom UI functionality involves two main components:
- The Command Class: A Python class that defines the button's icon, tooltip, text, and click action, registered into FreeCAD's GUI.
- The UI Dialog: A modal or non-modal window created via PySide to gather user input or display data.
Step 1: Create the PySide Dialog
You can build dialogs programmatically or design them using Qt
Designer and load the .ui file. The following example
builds a simple dialog entirely in Python:
from PySide import QtWidgets, QtCore
class CustomInputDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(CustomInputDialog, self).__init__(parent)
self.setWindowTitle("Custom Parameter Input")
self.resize(300, 150)
# Create Layout
layout = QtWidgets.QVBoxLayout(self)
# Add Label and Line Edit
self.label = QtWidgets.QLabel("Enter Dimension (mm):")
layout.addWidget(self.label)
self.input_field = QtWidgets.QLineEdit()
layout.addWidget(self.input_field)
# Add Standard OK/Cancel Buttons
self.button_box = QtWidgets.QDialogButtonBox(
QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
)
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.reject)
layout.addWidget(self.button_box)
def get_value(self):
return self.input_field.text()Step 2: Define the FreeCAD Command
FreeCAD requires a specific class structure to represent an action.
The class must implement GetResources() to define
appearance and Activated() to handle execution.
import FreeCAD as App
import FreeCADGui as Gui
class CustomToolCommand:
def GetResources(self):
return {
'Pixmap': 'Std_Tool1', # Built-in icon name or absolute path to a .svg/.png
'MenuText': 'Open Input Dialog',
'ToolTip': 'Opens a custom dialog to enter dimensions'
}
def Activated(self):
# Retrieve the main FreeCAD window as the parent
main_window = Gui.getMainWindow()
# Instantiate and display the dialog
dialog = CustomInputDialog(main_window)
if dialog.exec_():
user_value = dialog.get_value()
App.Console.PrintMessage(f"User entered: {user_value}\n")
def IsActive(self):
# Optional: return False if no document is open
return App.ActiveDocument is not NoneStep 3: Register the Command and Add the Button
To make the command accessible to the user, register it with the GUI system and append it to a toolbar or workbench.
Register the Command
Gui.addCommand('CustomTool_Command', CustomToolCommand())Add to an Existing Workbench Toolbar
To immediately test the button, you can inject it into an active workbench's toolbar directly via the Python console or a macro:
# Add to the current workbench toolbar
workbench = Gui.activeWorkbench()
workbench.addToolbarItem("Custom Tools", ["CustomTool_Command"])Making the Customization Persistent
To ensure your custom buttons and dialogs persist across FreeCAD sessions:
- Save as a Macro: Save the complete script into your FreeCAD macro directory (accessible via Macro > Macros...).
- Add to a Custom Toolbar via UI:
- Go to Tools > Customize > Toolbars.
- Select a workbench where the button should appear.
- Click New to create a custom toolbar category.
- Select Macros from the command category drop-down list.
- Select your registered macro command and click the right arrow to add it to the toolbar.
- Package as a Workbench: For complex tools, create
an
InitGui.pyfile within an addon directory inside~/.FreeCAD/Mod/(Linux/macOS) or%APPDATA%\FreeCAD\Mod\(Windows) to automatically create workbenches, toolbars, and menus on application startup.