מדריך: יצירת תוספים עבור FreeCAD
מטרת השיעור: לגרום לתוסף "בונה קופסאות" לזכור את הממדים האחרונים שהוזנו ולשחזר אותם בהפעלה הבאה.
חלק 1. כיצד FreeCAD מאחסן הגדרות?
FreeCAD מספק מנגנון מובנה לאחסון פרמטרים של המשתמש – דרך מנהל הפרמטרים (Parameter Manager).
המנגנון עובד עם מסד נתונים היררכי של פרמטרים, דומה ל-Windows Registry.
שיטות עיקריות:
# קבלת קבוצת פרמטרים
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/MyAddon")
# שמירת ערך
params.SetFloat("LastLength", 30.0)
params.SetString("LastName", "MyBox")
# טעינת ערך (עם ערך ברירת מחדל)
length = params.GetFloat("LastLength", 10.0) # 10.0 אם הפרמטר לא קיים
name = params.GetString("LastName", "DefaultBox")
הנתיב "User parameter:BaseApp/Preferences/..." הוא המיקום הסטנדרטי להגדרות משתמש.
חלק 2. תוסף מעודכן: "בונה קופסאות עם זיכרון"
נשפר את התוסף הקודם על ידי הוספת שמירה וטעינה של הערכים האחרונים.
קובץ box_builder_workbench.py (גרסה מעודכנת):
# box_builder_workbench.py
import FreeCAD, FreeCADGui
from PySide import QtGui, QtCore
# === נתיב להגדרות ===
PARAM_PATH = "User parameter:BaseApp/Preferences/BoxBuilderAddon"
def get_saved_settings():
"""טוען הגדרות שמורות או מחזיר ערכי ברירת מחדל"""
params = FreeCAD.ParamGet(PARAM_PATH)
return {
"length": params.GetFloat("LastLength", 30.0),
"width": params.GetFloat("LastWidth", 20.0),
"height": params.GetFloat("LastHeight", 10.0),
"name": params.GetString("LastName", "CustomBox")
}
def save_settings(length, width, height, name):
"""שומר את ההגדרות הנוכחיות"""
params = FreeCAD.ParamGet(PARAM_PATH)
params.SetFloat("LastLength", length)
params.SetFloat("LastWidth", width)
params.SetFloat("LastHeight", height)
params.SetString("LastName", name)
# === פונקציית יצירת הקופסה ===
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("בונה קופסאות")
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.resize(300, 180)
# טעינת הגדרות שמורות
settings = get_saved_settings()
# שדות קלט
self.length_input = QtGui.QLineEdit(str(settings["length"]))
self.width_input = QtGui.QLineEdit(str(settings["width"]))
self.height_input = QtGui.QLineEdit(str(settings["height"]))
self.name_input = QtGui.QLineEdit(settings["name"])
# כפתורים
self.create_button = QtGui.QPushButton("צור קופסה")
self.cancel_button = QtGui.QPushButton("ביטול")
# חיבור כפתורים
self.create_button.clicked.connect(self.on_create)
self.cancel_button.clicked.connect(self.reject)
# עיצוב
layout = QtGui.QFormLayout()
layout.addRow("שם:", self.name_input)
layout.addRow("אורך (מ\"מ):", self.length_input)
layout.addRow("רוחב (מ\"מ):", self.width_input)
layout.addRow("גובה (מ\"מ):", 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:
name = self.name_input.text().strip()
if not name:
name = "CustomBox"
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("כל הממדים חייבים להיות חיוביים")
# יצירת האובייקט
create_box(length, width, height, name)
# שמירת ההגדרות
save_settings(length, width, height, name)
self.accept()
except ValueError as e:
QtGui.QMessageBox.warning(self, "שגיאת קלט", f"קלט לא חוקי:\n{str(e)}")
# === פקודה וסביבת עבודה (ללא שינוי) ===
class BoxBuilderCommand:
def GetResources(self):
return {
"MenuText": "בונה קופסאות",
"ToolTip": "צור קופסה עם ממדים מותאמים אישית"
}
def Activated(self):
dialog = BoxBuilderDialog()
dialog.exec_()
def IsActive(self):
return True
class BoxBuilderWorkbench(FreeCADGui.Workbench):
MenuText = "בונה קופסאות"
ToolTip = "צור קופסאות מותאמות עם ממשק גרפי"
def Initialize(self):
self.list = ["BoxBuilderCommand"]
self.appendToolbar("כלי קופסאות", self.list)
self.appendMenu("בונה קופסאות", self.list)
def GetClassName(self):
return "Gui::PythonWorkbench"
FreeCADGui.addCommand("BoxBuilderCommand", BoxBuilderCommand())
מה השתנה?
- הוספנו פונקציות:
get_saved_settings()– טוענת את הערכים האחרוניםsave_settings()– שומרת את הערכים הנוכחיים
- נתיב לפרמטרים:
→ כל ההגדרות מאוחסנות בקבוצה נפרדת, ללא הפרעה לתוספים אחרים. - הוספנו שדה שם לממשק.
- בעת פתיחת החלון – השדות מתמלאים בערכים השמורים.
- לאחר יצירה – הערכים הנוכחיים נשמרים אוטומטית.
בדיקת תפקוד
- הפעל את FreeCAD
- פתח את "בונה קופסאות"
- הזן, למשל:
- שם:
MyTestBox - אורך:
50 - רוחב:
30 - גובה:
20
- לחץ על "צור קופסה"
- סגור את FreeCAD
- הפעל שוב
- פתח את "בונה קופסאות"
→ השדות אמורים להיות מלאים באותם ערכים!
איפה מאוחסנות ההגדרות?
- Windows: ב-Registry (
HKEY_CURRENT_USER\SOFTWARE\FreeCAD\...) - Linux/macOS: בקובץ
user.cfgבתיקיית FreeCAD
אבל אין צורך לדעת זאת – FreeCAD מנהל את מיקום האחסון בעצמו.
משימה מעשית
- הוסף תיבת סימון "מרכז בראשית הצירים" ושמור את מצבה בין הפעלות.
- ודא שבפעם הראשונה שהתוסף מופעל, נעשה שימוש בערכי ברירת מחדל הגיוניים (כבר מיושם).
- הוסף כפתור "איפוס לברירת מחדל" שמאפס את השדות לערכים הראשוניים ומוחק את ההגדרות השמורות.
רמז לאיפוס:
def reset_settings():
params = FreeCAD.ParamGet(PARAM_PATH)
params.RemGroup("BoxBuilderAddon") # מוחק את כל הקבוצה
טיפים
- תמיד ציין ערך ברירת מחדל ב-
GetFloat(),GetString()וכו'. - אל תשמור יותר מדי – רק מה שהמשתמש באמת צריך.
- השתמש בנתיב ייחודי (
BoxBuilderAddon) כדי להימנע מתנגנויות עם תוספים אחרים.
מה הלאה?
בשיעור 6 נלמד:
- להוסיף סמלים לכפתורים וסביבת העבודה
- ללמוד כיצד להשתמש ב-SVG ו-PNG בממשק
- להפוך את התוסף למשיכה ויזואלית