Skip to content
> 💻 🧠 קוד 1001 > 🧪📓 ללא קטגוריה > שיעור 4. ממשק משתמש גרפי (GUI): חלון דו-שיח עם שדות קלט

שיעור 4. ממשק משתמש גרפי (GUI): חלון דו-שיח עם שדות קלט

מדריך: יצירת תוספים עבור FreeCAD


חלק 1. כיצד פועל הממשק הגרפי ב-FreeCAD?
FreeCAD משתמש ב-PySide – מעטפת פייתון לספריית Qt (אותה ספריה המשמשת גם ב-Blender, Maya ותוכניות רבות אחרות).

רכיבים עיקריים:

  • QtGui.QDialog — חלון מודאלי
  • QtGui.QLineEdit — שדה קלט טקסט
  • QtGui.QPushButton — כפתור
  • QtGui.QFormLayout — עיצוב נוח בסגנון "תווית + שדה"

כל רכיבי הממשק נוצרים בתוך סקריפט פייתון – ללא קבצים חיצוניים (למרות שניתן להשתמש בקבצי .ui מתוך Qt Designer; נתחיל עם משהו פשוט).


חלק 2. תוסף: "בונה קופסאות עם ממשק גרפי"
נשפר את התוסף הקודם על ידי הוספת חלון דו-שיח.

שלב 1. יצירת תיקייה

.../Mod/BoxBuilderAddon/

שלב 2. קובץ InitGui.py

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

FreeCADGui.addWorkbench(BoxBuilderWorkbench())

שלב 3. קובץ box_builder_workbench.py

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

# === פונקציית יצירת הקופסה ===
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, 150)

        # שדות קלט
        self.length_input = QtGui.QLineEdit("30.0")
        self.width_input = QtGui.QLineEdit("20.0")
        self.height_input = QtGui.QLineEdit("10.0")

        # כפתורים
        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.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:
            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)
            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())

ניתוח החלקים המרכזיים

  1. חלון דו-שיח (BoxBuilderDialog)
  • יורש מ-QtGui.QDialog
  • משתמש ב-QFormLayout לארגון נקי של השדות
  • הכפתור "צור קופסה" מפעיל את on_create(), וכפתור "ביטול" סוגר את החלון
  1. עיבוד קלט
  • ממיר טקסט ל-float
  • בודק שהערכים חיוביים
  • במקרה של שגיאה – מציג אזהרה באמצעות QMessageBox.warning
  1. יצירת אובייקט
  • הפונקציה create_box() מופרדת – לקוד נקי
  • מייצר שם ייחודי כדי להימנע מתנגנויות
  1. הפעלת החלון
  • dialog.exec_() הופך את החלון למודאלי (לא ניתן לערוך את FreeCAD בזמן שהוא פתוח)

שלב 4. בדיקת תפקוד

  1. שמור את הקבצים
  2. הפעל מחדש את FreeCAD
  3. בחר את סביבת העבודה "בונה קופסאות"
  4. לחץ על הכפתור "בונה קופסאות"
  5. הזן ממדים בחלון שמופיע → לחץ על "צור קופסה"

קופסה עם הפרמטרים שלך אמורה להופיע!

נסה את הדברים הבאים:

  • הזן אותיות → תופיע שגיאה
  • הזן מספר שלילי → שגיאה
  • הזן מספרים עשרוניים (למשל 12.5) → עובד!

משימה מעשית

  1. הוסף שדה רביעי: "שם" – כדי שהמשתמש יוכל לקבוע את שם האובייקט.
  2. ודא שאם השם ריק, יוגדר ערך ברירת מחדל ("CustomBox").
  3. הוסף תיבת סימון "מרכז בראשית הצירים" – אם מסומן, הקופסה תتمركز בראשית הצירים.

רמז למרכזון:
לאחר יצירת הקופסה, שנה את מאפיין ה-Placement:

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

טיפים לעבודה עם ממשק גרפי

  • תמיד עטוף קלט ב-try/except – המשתמש יכול להזין כל דבר
  • באפשרותך להשתמש ב-QDoubleValidator כדי לאפשר רק מספרים (אופציונלי)
  • עבור ממשקים מורכבים עדיף להשתמש ב-Qt Designer ולטעון קבצי .ui, אך עבור משימות פשוטות – הקוד קל יותר

מה הלאה?
בשיעור 5 נלמד:

  • כיצד לשמור הגדרות בין הפעלות של FreeCAD
  • לוודא שערכי הממדים האחרונים נשמרים
  • להשתמש במנגנון המובנה של FreeCAD: FreeCAD.ParamGet()

כך התוסף שלך יהפוך לנוח עוד יותר!

שיעור 4. ממשק משתמש גרפי (GUI): חלון דו-שיח עם שדות קלט
מאת hypo69 / 03.10.2025

מדריך: יצירת תוספים עבור FreeCAD

מטרת השיעור: צור חלון עם שדות להזנת אורך, רוחב וגובה, ובנה קופסה עם פרמטרים אלו בלחיצה על כפתור.


חלק 1. כיצד פועל הממשק הגרפי ב-FreeCAD?
FreeCAD משתמש ב-PySide – מעטפת פייתון לספריית Qt (אותה ספריה המשמשת גם ב-Blender, Maya ותוכניות רבות אחרות).

רכיבים עיקריים:

  • QtGui.QDialog — חלון מודאלי
  • QtGui.QLineEdit — שדה קלט טקסט
  • QtGui.QPushButton — כפתור
  • QtGui.QFormLayout — עיצוב נוח בסגנון "תווית + שדה"

כל רכיבי הממשק נוצרים בתוך סקריפט פייתון – ללא קבצים חיצוניים (למרות שניתן להשתמש בקבצי .ui מתוך Qt Designer; נתחיל עם משהו פשוט).


חלק 2. תוסף: "בונה קופסאות עם ממשק גרפי"
נשפר את התוסף הקודם על ידי הוספת חלון דו-שיח.

שלב 1. יצירת תיקייה

.../Mod/BoxBuilderAddon/

שלב 2. קובץ InitGui.py

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

FreeCADGui.addWorkbench(BoxBuilderWorkbench())

שלב 3. קובץ box_builder_workbench.py

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

# === פונקציית יצירת הקופסה ===
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, 150)

        # שדות קלט
        self.length_input = QtGui.QLineEdit("30.0")
        self.width_input = QtGui.QLineEdit("20.0")
        self.height_input = QtGui.QLineEdit("10.0")

        # כפתורים
        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.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:
            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)
            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())

ניתוח החלקים המרכזיים

  1. חלון דו-שיח (BoxBuilderDialog)
  • יורש מ-QtGui.QDialog
  • משתמש ב-QFormLayout לארגון נקי של השדות
  • הכפתור "צור קופסה" מפעיל את on_create(), וכפתור "ביטול" סוגר את החלון
  1. עיבוד קלט
  • ממיר טקסט ל-float
  • בודק שהערכים חיוביים
  • במקרה של שגיאה – מציג אזהרה באמצעות QMessageBox.warning
  1. יצירת אובייקט
  • הפונקציה create_box() מופרדת – לקוד נקי
  • מייצר שם ייחודי כדי להימנע מתנגנויות
  1. הפעלת החלון
  • dialog.exec_() הופך את החלון למודאלי (לא ניתן לערוך את FreeCAD בזמן שהוא פתוח)

שלב 4. בדיקת תפקוד

  1. שמור את הקבצים
  2. הפעל מחדש את FreeCAD
  3. בחר את סביבת העבודה "בונה קופסאות"
  4. לחץ על הכפתור "בונה קופסאות"
  5. הזן ממדים בחלון שמופיע → לחץ על "צור קופסה"

קופסה עם הפרמטרים שלך אמורה להופיע!

נסה את הדברים הבאים:

  • הזן אותיות → תופיע שגיאה
  • הזן מספר שלילי → שגיאה
  • הזן מספרים עשרוניים (למשל 12.5) → עובד!

משימה מעשית

  1. הוסף שדה רביעי: "שם" – כדי שהמשתמש יוכל לקבוע את שם האובייקט.
  2. ודא שאם השם ריק, יוגדר ערך ברירת מחדל ("CustomBox").
  3. הוסף תיבת סימון "מרכז בראשית הצירים" – אם מסומן, הקופסה תتمركز בראשית הצירים.

רמז למרכזון:
לאחר יצירת הקופסה, שנה את מאפיין ה-Placement:

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

טיפים לעבודה עם ממשק גרפי

  • תמיד עטוף קלט ב-try/except – המשתמש יכול להזין כל דבר
  • באפשרותך להשתמש ב-QDoubleValidator כדי לאפשר רק מספרים (אופציונלי)
  • עבור ממשקים מורכבים עדיף להשתמש ב-Qt Designer ולטעון קבצי .ui, אך עבור משימות פשוטות – הקוד קל יותר

מה הלאה?
בשיעור 5 נלמד:

  • כיצד לשמור הגדרות בין הפעלות של FreeCAD
  • לוודא שערכי הממדים האחרונים נשמרים
  • להשתמש במנגנון המובנה של FreeCAD: FreeCAD.ParamGet()

כך התוסף שלך יהפוך לנוח עוד יותר!

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *