Przejdź do treści
> 💻 🧠 Kod 1001 > 🧪📓 Bez kategorii > Lekcja 4. Graficzny Interfejs Użytkownika (GUI): Okno Dialogowe z Polami Wejściowymi – Code 1001

Lekcja 4. Graficzny Interfejs Użytkownika (GUI): Okno Dialogowe z Polami Wejściowymi – Code 1001

Tutorial: Tworzenie Dodatków dla FreeCAD

Cel Lekcji: Stworzenie okna z polami do wprowadzania długości, szerokości i wysokości, a następnie zbudowanie prostopadłościanu z tymi parametrami po kliknięciu przycisku.

W Tym Artykule

  • 01 Część 1. Jak działa GUI w FreeCAD?
  • 02 Część 2. Dodatek: „Box Builder with GUI” (Kreator Prostopadłościanów z GUI)
    • Krok 1. Utwórz folder
    • Krok 2. Plik InitGui.py
    • Krok 3. Plik box_builder_workbench.py
      • Rozbicie Kluczowych Części
          1. Okno Dialogowe ($\text{BoxBuilderDialog}$)
          1. Przetwarzanie Wejścia
          1. Tworzenie Obiektu
          1. Uruchomienie Okna
  • 04 Krok 4. Sprawdzenie Działania
  • 05 Zadanie Praktyczne
  • 06 Wskazówki do Pracy z GUI
  • 07 Co dalej?

Część 1. Jak działa GUI w FreeCAD?

FreeCAD używa $\text{PySide}$ – wrappera Pythona dla biblioteki Qt (tej samej, której używają Blender, Maya i wiele innych programów).

Kluczowe komponenty:

  • $\text{QtGui.QDialog}$ – okno modalne
  • $\text{QtGui.QLineEdit}$ – pole do wprowadzania tekstu
  • $\text{QtGui.QPushButton}$ – przycisk
  • $\text{QtGui.QFormLayout}$ – wygodny układ „etykieta + pole”

Wszystkie elementy GUI są tworzone wewnątrz skryptu Pythona, bez plików zewnętrznych (chociaż można użyć $\text{ui}$ z $\text{Qt Designer}$ – ale zaczniemy od czegoś prostego).


Część 2. Dodatek: „Box Builder with GUI”

Rozszerzymy poprzedni dodatek, dodając okno dialogowe.

Krok 1. Utwórz folder

$\text{…/Mod/BoxBuilderAddon/}$

Krok 2. Plik InitGui.py

Python

# InitGui.py
import FreeCADGui
from BoxBuilderAddon.box_builder_workbench import BoxBuilderWorkbench
FreeCADGui.addWorkbench(BoxBuilderWorkbench())

Krok 3. Plik box_builder_workbench.py

Python

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

# === FUNKCJA TWORZENIA PROSTOPADŁOŚCIANU ===
def create_box(length, width, height, name="CustomBox"):
    doc = FreeCAD.ActiveDocument
    if not doc:
        doc = FreeCAD.newDocument("BoxBuilder")

    # Unikalna nazwa
    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

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

        # Pola wejściowe
        self.length_input = QtGui.QLineEdit("30.0")
        self.width_input = QtGui.QLineEdit("20.0")
        self.height_input = QtGui.QLineEdit("10.0")

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

        # Łączenie przycisków
        self.create_button.clicked.connect(self.on_create)
        self.cancel_button.clicked.connect(self.reject)

        # Układ (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() # Zamknij okno
        except ValueError as e:
            QtGui.QMessageBox.warning(self, "Input Error", f"Invalid input:\n{str(e)}")

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

    def Activated(self):
        dialog = BoxBuilderDialog()
        dialog.exec_() # Wywołanie modalne

    def IsActive(self):
        return True

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

Rozbicie Kluczowych Części

  1. Okno Dialogowe ($\text{BoxBuilderDialog}$)
    • Dziedziczy z $\text{QtGui.QDialog}$
    • Używa $\text{QFormLayout}$ do uporządkowanego umieszczania pól
    • Przycisk „Create Box” wywołuje $\text{on\_create()}$, „Cancel” zamyka okno
  2. Przetwarzanie Wejścia
    • Konwertuje tekst na liczbę zmiennoprzecinkową ($\text{float}$)
    • Sprawdza, czy wartości są dodatnie
    • W przypadku błędu wyświetla ostrzeżenie za pomocą $\text{QMessageBox.warning}$
  3. Tworzenie Obiektu
    • Funkcja $\text{create\_box()}$ jest wydzielona dla czystszego kodu
    • Generuje unikalną nazwę, aby uniknąć konfliktów
  4. Uruchomienie Okna
    • $\text{dialog.exec\_()}$ sprawia, że okno jest modalne (nie można wchodzić w interakcję z FreeCAD, gdy jest otwarte)

Krok 4. Sprawdzenie Działania

  1. Zapisz pliki
  2. Uruchom ponownie FreeCAD
  3. Wybierz środowisko pracy „Box Builder„
  4. Kliknij przycisk „Box Builder„
  5. W oknie, które się pojawi, wprowadź wymiary $\rightarrow$ kliknij $\text{Create Box}$
    • Powinien pojawić się prostopadłościan z Twoimi parametrami!

Wypróbuj:

  • Wprowadzenie liter $\rightarrow$ pojawi się błąd
  • Wprowadzenie liczby ujemnej $\rightarrow$ błąd
  • Wprowadzenie liczb ułamkowych (np. 12.5) działa!

Zadanie Praktyczne

  1. Dodaj czwarte pole: „Nazwa” – aby użytkownik mógł ustawić nazwę obiektu.
  2. Upewnij się, że jeśli nazwa jest pusta, zostanie użyta domyślna wartość („$\text{CustomBox}$”).
  3. Dodaj pole wyboru ($\text{checkbox}$) „Center on origin” (Wyśrodkuj na początku układu współrzędnych) $\rightarrow$ jeśli jest włączone, prostopadłościan powinien być wyśrodkowany.

Wskazówka do centrowania:

Po utworzeniu prostopadłościanu zmień jego właściwość $\text{Placement}$:

Python

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

Wskazówki do Pracy z GUI

  • Zawsze owijaj wprowadzanie danych w $\text{try/except}$ $\rightarrow$ użytkownik może wprowadzić cokolwiek
  • Użyj $\text{QDoubleValidator}$, aby zezwolić tylko na liczby (opcjonalnie)
  • Dla bardziej złożonych interfejsów lepiej jest użyć $\text{Qt Designer}$ i ładować pliki $\text{.ui}$, ale dla prostych zadań kod jest łatwiejszy

Co dalej?

W Lekcji 5 nauczymy się:

  • Jak zapisywać ustawienia pomiędzy uruchomieniami FreeCAD
  • Zapewnić zapamiętanie ostatnio wprowadzonej wartości wymiaru
  • Użyć wbudowanego mechanizmu FreeCAD: $\text{FreeCAD.ParamGet()}$
  • To sprawi, że Twój dodatek będzie jeszcze wygodniejszy!

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *