Grouping text as a whole object (eventually in FeaturePyhton)
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Grouping text as a whole object (eventually in FeaturePyhton)
Hello,
Here is the script:
I want to create a parametric "ruler" in a 3D view. So far, I managed to do that:
The Ruler Lines are grouped under a App::FeaturePython and is driven by parameters as expected.
My question concern the labels. They are made using :
Which leads to a bunch of labels in the tree. My question is how to group all those labels under the "Ruler" FeaturePython, such as I can drive all the labels with a single parameter (like font size, color, etc...)
Here is the script:
I want to create a parametric "ruler" in a 3D view. So far, I managed to do that:
The Ruler Lines are grouped under a App::FeaturePython and is driven by parameters as expected.
My question concern the labels. They are made using :
Which leads to a bunch of labels in the tree. My question is how to group all those labels under the "Ruler" FeaturePython, such as I can drive all the labels with a single parameter (like font size, color, etc...)
Re: Grouping text as a whole object (eventually in FeaturePyhton)
Some progress on this. Using This thread, I added ``App::GroupExtensionPython`` Extension.
It correctly groups my labels under a FeaturePython object. Youhou! I can even change the font size for all my labels by using the relevant parameter in "RulerLabels".
Unfortunately, this does not survive to serialisation, despite ``__setstate__``:
Code: Select all
class RulerLabel:
# [...]
def __setstate__(self, data):
obj.addExtension("App::GroupExtensionPython")
# [...]
Re: Grouping text as a whole object (eventually in FeaturePyhton)
OK, I think that one of the problems is the serialization.
serializing label texts will work much better:
Now, next problem is that when I reopen my file, I have errors :
Those errors make sense since Those Classes are defined in my macros... This is automatically solved with importing the Macro in Python namespace:
So, I think I solved my issue.
Now, I realize that GroupExtensionPython was maybe not what I needed, since I would like the whole Ruler to be a single object without subtree. I'm open to any idea...
serializing label texts will work much better:
Code: Select all
class RulerLabel:
def __init__(self, obj):
obj.addProperty("App::PropertyLength", "yLoc", "Aspect", "Y loc")
obj.addProperty("App::PropertyLength", "txtOffset", "Aspect", "text Offset")
obj.addProperty("App::PropertyLength", "txtSize", "Aspect", "text Size")
obj.addExtension("App::GroupExtensionPython")
obj.yLoc = 5000 # mm
obj.txtOffset = 500 # mm
obj.txtSize = 400 # mm
self.labels = []
obj.Proxy = self
def __getstate__(self):
return self.labels
def __setstate__(self, data):
label_objs = [App.ActiveDocument.getObjectsByLabel(txt)[0] for txt in data]
for label_obj in label_objs:
label_obj.LinkToParent = fp
obj.addExtension("App::GroupExtensionPython")
def execute(self, fp):
for x, txt in GRID.items():
# -----------------------------------------------------------------
pl = App.Placement()
# rotate 45°
pl.Rotation.Q = (0.0, 0.0, 0.3826834323650898, 0.9238795325112867)
# search if we already have this label
objs = App.ActiveDocument.getObjectsByLabel(txt)
pl.Base = App.Vector(x, fp.yLoc + fp.txtOffset, 0.0)
if not objs:
# create label
_text_ = Draft.make_text([txt], placement=pl, screen=False)
_text_.ViewObject.FontSize = fp.txtSize
_text_.Label = txt
_text_.addProperty("App::PropertyLink", "LinkToParent")
_text_.LinkToParent = fp
self.labels.append(txt)
else:
# update label
_text_ = objs[0]
_text_.ViewObject.FontSize = fp.txtSize
Code: Select all
17:16:34 <string>(1)<class 'AttributeError'>: Module __main__ has no class RulerLines
17:16:34 <string>(1)<class 'AttributeError'>: Module __main__ has no class RulerLabel
17:16:34 <string>(1)<class 'AttributeError'>: Module __main__ has no class ViewProviderRulerLines
17:16:34 <string>(1)<class 'AttributeError'>: Module __main__ has no class ViewProviderRulerLabel
Code: Select all
import imp
AC_grid2 = imp.load_source("AC_grid2", "/home/nic/.FreeCAD/Macro/AC_grid2.FCMacro")
Now, I realize that GroupExtensionPython was maybe not what I needed, since I would like the whole Ruler to be a single object without subtree. I'm open to any idea...
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Grouping text as a whole object (eventually in FeaturePyhton)
As an alternative to the extension if you use claimChildren() in the view provider class you can return the objects as a list that you want to have inside the tree heirarchy.
If you don't want the objects appearing in the tree:
for obj in myobjects:
obj.ViewObject.ShowInTree = False
Just remember to also remove them if the user deletes your fp object, especially important if they are hidden in the tree. This can be done in onDelete() of the view provider. Care should be taken to always return True so the object itself can be deleted. Presuming you have the list of objects saved as a App::PropertyLinkList named Items, this should work (untested and might be better in try/except blocks so True can always be returned):
Code: Select all
def claimChildren(self):
if you want to claim children:
return [list of document objects]
else:
return []
for obj in myobjects:
obj.ViewObject.ShowInTree = False
Just remember to also remove them if the user deletes your fp object, especially important if they are hidden in the tree. This can be done in onDelete() of the view provider. Care should be taken to always return True so the object itself can be deleted. Presuming you have the list of objects saved as a App::PropertyLinkList named Items, this should work (untested and might be better in try/except blocks so True can always be returned):
Code: Select all
def onDelete(self, vobj, subelements):
if vobj.Object.Items:
for item in vobj.Object.Items:
FreeCAD.ActiveDocument.remove(item.Name)
return True
Re: Grouping text as a whole object (eventually in FeaturePyhton)
Yes, this looks promising. I almost have it done, but face some strange recomputes issues:
Thanks for your help, TheMarkster
Code: Select all
...
21:46:19 689.982 <App> Document.cpp(3539): Sans_nom#Text012 still touched after recompute
21:46:19 689.982 <App> Document.cpp(3539): Sans_nom#Text013 still touched after recompute
...
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Grouping text as a whole object (eventually in FeaturePyhton)
Creating document objects during execute() can be problematic. One trick can be to put the object creation in another function and call it with a singleshot, which gets executed after execute() has returned.
If you need to access the fp object inside makeSomeObject() you can create a string variable in __init__():
Then in makeSomeObject():
Code: Select all
def makeSomeObject(self):
#make the object
#recompute
def execute(self,fp):
from PySide import QtCore
QtCore.QTimer().singleShot(50, self.makeSomeObject)
Code: Select all
self.fpName = obj.Name
Code: Select all
fp = FreeCAD.ActiveDocument.getObject(self.fpName)
Re: Grouping text as a whole object (eventually in FeaturePyhton)
Yes, this works very well.TheMarkster wrote: ↑Wed Nov 17, 2021 10:08 pm One trick can be to put the object creation in another function and call it with a singleshot, which gets executed after execute() has returned.
The next point was to make labels invisible. Setting the `ShownInTree` attribute to False is working well, except for the last item which remains visible with an "eye" overlay. The Forum Tree View section doesn not talk about it, and I couldn't find references elsewhere.
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: Grouping text as a whole object (eventually in FeaturePyhton)
I'm not sure why that last label is still showing up in the tree.
One issue is the object is constantly recomputing. This can be solved by adding a flag:
in init()
self.inhibitRecomputes = False
in execute()
if self.inhibitRecomputes:
self.inhibitRecomputes = False
return
in _execute()
self.inhibitRecomputes = True
I'll attach the file with these changes.
If you toggle App.ActiveDocument.ShowHidden = True, and then back to False again in the python console it hides the label, but doesn't seem to work in the script. But with some experimentation it might be made to work.
One issue is the object is constantly recomputing. This can be solved by adding a flag:
in init()
self.inhibitRecomputes = False
in execute()
if self.inhibitRecomputes:
self.inhibitRecomputes = False
return
in _execute()
self.inhibitRecomputes = True
I'll attach the file with these changes.
If you toggle App.ActiveDocument.ShowHidden = True, and then back to False again in the python console it hides the label, but doesn't seem to work in the script. But with some experimentation it might be made to work.
- Attachments
-
- AC_grid4.FCMacro
- (5.48 KiB) Downloaded 24 times
Re: Grouping text as a whole object (eventually in FeaturePyhton)
Really nice tip! Many thanks.TheMarkster wrote: ↑Thu Nov 18, 2021 5:32 pm in init()
self.inhibitRecomputes = False
in execute()
if self.inhibitRecomputes:
self.inhibitRecomputes = False
return
in _execute()
self.inhibitRecomputes = True
This last item not hidden is driving me crazy since this morning...