How to set class attributes using the freecad widget

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
FreundBlume
Posts: 8
Joined: Wed Jan 16, 2019 2:01 pm
Location: Berlin

How to set class attributes using the freecad widget

Post by FreundBlume »

Hi All,

I have successfully completed the tutorial regarding the creation of interfaces.
https://www.freecadweb.org/wiki/Manual: ... face_tools
I still have the problem, that the widget is not completely displayed (see picture), but that is something I postponed for the moment.
The problem I actually got stuck with is the following:
I want to extent the class of the example with properties for length, width and height so that it is possible to change the values later.
Based on this tutorial (https://www.freecadweb.org/wiki/Manual: ... ic_objects) I have tried to set the values using the values by:
Defining the property in the init section obj.addProperty("App::PropertyFloat","Length")
and changing the line from the interface tutorial:

Code: Select all

length = self.form.BoxLength.value()
to

Code: Select all

obj.Length =  self.form.BoxLength.value()
Using the obj.Length I think I also have to transfer the obj to the accept function, but I fail with following error output in freecad:
<unknown exception traceback><type 'exceptions.TypeError'>: accept() takes exactly 2 arguments (1 given)
Could please anybody give me a hint, how to connect the widget with the class properties in an elegant way?

Below is my current (not working) editing status of the interface tutorial:

Code: Select all

import FreeCAD, FreeCADGui, Part

# CHANGE THE LINE BELOW
path_to_ui = "/home/.../.../.../dialog.ui"

class PartFeature:
	def __init__(self, obj):
		obj.Proxy = self

class BoxTaskPanel():
    def __init__(self,obj):
        obj.addProperty("App::PropertyFloat", "Length")
        # this will create a Qt widget from our ui file
        self.form = FreeCADGui.PySideUic.loadUi(path_to_ui)

    def accept(self,obj):
        # length = fp.form.BoxLength.value()
        obj.Length = self.form.BoxLength.value()
        length = obj.Length
        width = self.form.BoxWidth.value()
        height = self.form.BoxHeight.value()
        if (length == 0) or (width == 0) or (height == 0):
            print("Error! None of the values can be 0!")
            # we bail out without doing anything
            return
        box = Part.makeBox(length, width, height)

        # Part.show(box)
        # FreeCADGui.Control.closeDialog()

        box.Placement = obj.Placement
        obj.Shape = box

myObj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Box")
panel = BoxTaskPanel(myObj)
FreeCADGui.Control.showDialog(panel)
myObj.ViewObject.Proxy = 0
FreeCAD.ActiveDocument.recompute()

OS: Ubuntu 18.04.3 LTS
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.4.
Build type: Release
Python version: 2.7.15+
Qt version: 5.9.5
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: German/Germany (de_DE)
Attachments
IncompleteWidget.png
IncompleteWidget.png (13.48 KiB) Viewed 754 times
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: How to set class attributes using the freecad widget

Post by wmayer »

Can you also upload the file dialog.ui? It looks like there is something wrong or missing, e.g. the layout.
vocx
Veteran
Posts: 5197
Joined: Thu Oct 18, 2018 9:18 pm

Re: How to set class attributes using the freecad widget

Post by vocx »

FreundBlume wrote: Sun Dec 29, 2019 6:09 pm ...

Code: Select all

obj.Length =  self.form.BoxLength.value()
It really depends on what BoxLength is. Is it a spin box, an input field? Is it a FreeCAD specific widget Gui::InputField, etc?

If BoxLength has some units, you may need to extract the quantity in a special way. So, yes, you need to show the .ui file that you are loading.
Last edited by vocx on Mon Dec 30, 2019 8:07 am, edited 1 time in total.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
FreundBlume
Posts: 8
Joined: Wed Jan 16, 2019 2:01 pm
Location: Berlin

Re: How to set class attributes using the freecad widget

Post by FreundBlume »

wmayer wrote: Sun Dec 29, 2019 11:04 pm Can you also upload the file dialog.ui? It looks like there is something wrong or missing, e.g. the layout.
Sorry, I forgot to attach the file to the original post.
dialog.ui
(2.19 KiB) Downloaded 23 times
vocx wrote: Sun Dec 29, 2019 11:34 pm It really depends on what BoxLength is. Is it a spin box, an input field? Is it a FreeCAD specific widget Gui::InputField, etc?

If BoxLength has some units, you may need to extract the quantity in a special way. So, yes, you need to show the .ui file that you are loading.
I used a DoubleSpinBox as in the tutorial, but did not use any units.
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: How to set class attributes using the freecad widget

Post by wmayer »

It's like I said that no grid layout is set. Attached is the fixed file.
Attachments
dialog.ui
(2.14 KiB) Downloaded 28 times
FreundBlume
Posts: 8
Joined: Wed Jan 16, 2019 2:01 pm
Location: Berlin

Re: How to set class attributes using the freecad widget

Post by FreundBlume »

wmayer wrote: Mon Dec 30, 2019 10:29 am It's like I said that no grid layout is set. Attached is the fixed file.
Thanks a lot for the fixed file and the quick response. I now understand what I have done wrong.

Do you also have an idea how I can transfer the input of the widget to a class property.
I want to change the size of the box after it is created by just changing the class property in the data tab of the box.
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: How to set class attributes using the freecad widget

Post by wmayer »

Code: Select all

import FreeCAD, FreeCADGui, Part

# CHANGE THE LINE BELOW
path_to_ui = "/tmp/dialog.ui"

class PartFeature:
    def __init__(self, obj):
        obj.Proxy = self
        obj.addProperty("App::PropertyFloat", "Length")
        obj.addProperty("App::PropertyFloat", "Width")
        obj.addProperty("App::PropertyFloat", "Height")
    def execute(self, obj):
        obj.Shape = Part.makeBox(obj.Length, obj.Width, obj.Height)

class BoxTaskPanel():
    def __init__(self,obj):
        # this will create a Qt widget from our ui file
        self.form = FreeCADGui.PySideUic.loadUi(path_to_ui)
        self.form.BoxLength.setValue(obj.Length)
        self.form.BoxWidth.setValue(obj.Width)
        self.form.BoxHeight.setValue(obj.Height)
        self.obj = obj
    
    def accept(self):
        length = self.form.BoxLength.value()
        width = self.form.BoxWidth.value()
        height = self.form.BoxHeight.value()
        if (length == 0) or (width == 0) or (height == 0):
            print("Error! None of the values can be 0!")
            # we bail out without doing anything
            return False
        # length = fp.form.BoxLength.value()
        self.obj.Length = length
        self.obj.Width = width
        self.obj.Height = height
        self.obj.recompute()
        return True

myObj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Box")
PartFeature(myObj)
myObj.ViewObject.Proxy = 0

panel = BoxTaskPanel(myObj)
FreeCADGui.Control.showDialog(panel)
FreundBlume
Posts: 8
Joined: Wed Jan 16, 2019 2:01 pm
Location: Berlin

Re: How to set class attributes using the freecad widget

Post by FreundBlume »

Thanks a lot for the code.
If I understand it right:
  • the class PartFeature defines the geometry and the attributes
  • the class BoxTaskPanel initializes the widget and assigns the values
  • the command PartFeature(myObj) assigns a new PartFeature instance to myObj
  • the command BoxTaskPanel(myObj) adds a new instance of BoxTaskPanel to myObj
Is that correct?

Just one more question: Is the labeling of the class PartFeature as "PartFeature" random or does it follow some FreeCAD coding convention?

Thanks again for the quick help.
Happy new Year!
vocx
Veteran
Posts: 5197
Joined: Thu Oct 18, 2018 9:18 pm

Re: How to set class attributes using the freecad widget

Post by vocx »

Just a word of caution. Those wiki pages that you've followed, about creating objects and dealing with the user interface, may be very outdated. In general, FreeCAD's programming documentation meant for power users and developers is a bit old. User documentation, that is, how to use the principal workbenches, Draft, Arch, PartDesign, Sketcher, etc., is in better shape.

Documenting isn't an easy task, so I've focused my efforts on writing more complete user documentation first, and I've neglected the advanced documentation. The reason is that power users generally know how to research things themselves, so they need less information, just general guidelines.

Reading those wiki pages is good, but if you really want to know how some things are implemented, I suggest you look at some existing code. For example, take a look at some of the classes in FEM that launch a task panel.

https://github.com/FreeCAD/FreeCAD/blob ... 1D.py#L106
FreundBlume wrote: Mon Dec 30, 2019 4:14 pm ...
Just one more question: Is the labeling of the class PartFeature as "PartFeature" random or does it follow some FreeCAD coding convention?
...
About the "PartFeature" question, I'm not sure what you are asking.

In FreeCAD "Part::Feature" (Part_Feature) is a class that defines the basic object that holds and manages a topological shape (Part_TopoShape). Almost every 3D "thing" that you see in the 3D view is in some way derived from "Part::Feature".

In the example from wmayer, he creates a class "PartFeature" to customize a "Part::FeaturePython" object. The name "PartFeature" is arbitrary. I would have called it "MyObject", or "MyBoxObject", or "CustomBoxObject", or something more meaningful to my particular object. The "Part::FeaturePython" class is the same basic "Part::Feature", but for Python scripting.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
FreundBlume
Posts: 8
Joined: Wed Jan 16, 2019 2:01 pm
Location: Berlin

Re: How to set class attributes using the freecad widget

Post by FreundBlume »

Thanks for the additional links and hints :)
Post Reply