摘要:該模塊將對象轉換為字符串,允許將其添加到保存的文件中。返回所有可序列化對象的元組或無。財產類型默認情況下,可以更新屬性。這可以通過函數完成。
除了標注對象類型(如注釋,網格和零件對象)之外,FreeCAD還提供了構建100%python腳本對象(稱為Python功能)的可能性。這些對象的行為與任何其他FreeCAD對象完全相同,并在文件保存/加載時自動保存和恢復。
這些對象使用python的json模塊保存在FreeCAD FcStd文件中。該模塊將python對象轉換為字符串,允許將其添加到保存的文件中。在加載時,json模塊使用該字符串重新創建原始對象,前提是它可以訪問創建該對象的源代碼。這意味著如果保存這樣的自定義對象并在不存在生成該對象的python代碼的機器上打開它,則不會重新創建該對象。如果將這些對象分發給其他人,則需要分發創建它的python腳本。
Python功能遵循與所有FreeCAD功能相同的規則:它們分為App和GUI部分。應用程序部分Document對象定義了對象的幾何形狀,而GUI部分View Provider Object定義了如何在屏幕上繪制對象。與任何其他FreeCAD功能一樣,View Provider Object僅在您自己的GUI中運行FreeCAD時可用。有幾個屬性和方法可用于構建對象。屬性必須是FreeCAD提供的任何預定義屬性類型,并且將顯示在屬性視圖窗口中,以便用戶可以編輯它們。這樣,FeaturePython對象就是真正完全參數化的。您可以多帶帶定義Object及其ViewObject的屬性。
提示:在以前的版本中,我們使用了Python的cPickle模塊。但是,該模塊執行任意代碼,從而導致安全問題。因此,我們轉向Python的json模塊。
基本的例子可以在src / Mod / TemplatePyMod / FeaturePython.py文件中找到以下示例,以及其他幾個示例:
"""Examples for a feature class and its view provider.""" import FreeCAD, FreeCADGui from pivy import coin class Box: def __init__(self, obj): """添加Box自定義屬性特征""" obj.addProperty("App::PropertyLength","Length","Box","Length of the box").Length=1.0 obj.addProperty("App::PropertyLength","Width","Box","Width of the box").Width=1.0 obj.addProperty("App::PropertyLength","Height","Box", "Height of the box").Height=1.0 obj.Proxy = self def onChanged(self, fp, prop): """定義屬性改變時的操作""" FreeCAD.Console.PrintMessage("Change property: " + str(prop) + " ") def execute(self, fp): """在進行重新計算時執行某些操作,此方法是必需的""" FreeCAD.Console.PrintMessage("Recompute Python Box feature ") class ViewProviderBox: def __init__(self, obj): """將此對象設置為實際視圖提供者的代理對象Set this object to the proxy object of the actual view provider""" obj.addProperty("App::PropertyColor","Color","Box","Color of the box").Color=(1.0,0.0,0.0) obj.Proxy = self def attach(self, obj): """設置視圖提供者的場景子圖,這個方法是強制性的Setup the scene sub-graph of the view provider, this method is mandatory""" self.shaded = coin.SoGroup() self.wireframe = coin.SoGroup() self.scale = coin.SoScale() self.color = coin.SoBaseColor() data=coin.SoCube() self.shaded.addChild(self.scale) self.shaded.addChild(self.color) self.shaded.addChild(data) obj.addDisplayMode(self.shaded,"Shaded"); style=coin.SoDrawStyle() style.style = coin.SoDrawStyle.LINES self.wireframe.addChild(style) self.wireframe.addChild(self.scale) self.wireframe.addChild(self.color) self.wireframe.addChild(data) obj.addDisplayMode(self.wireframe,"Wireframe"); self.onChanged(obj,"Color") def updateData(self, fp, prop): """如果已處理功能的屬性已更改,我們有機會在此處理此If a property of the handled feature has changed we have the chance to handle this here""" # fp is the handled feature, prop is the name of the property that has changed l = fp.getPropertyByName("Length") w = fp.getPropertyByName("Width") h = fp.getPropertyByName("Height") self.scale.scaleFactor.setValue(float(l),float(w),float(h)) pass def getDisplayModes(self,obj): """返回顯示模式列表Return a list of display modes.""" modes=[] modes.append("Shaded") modes.append("Wireframe") return modes def getDefaultDisplayMode(self): """返回默認顯示模式的名稱。它必須在getDisplayModes中定義。Return the name of the default display mode. It must be defined in getDisplayModes.""" return "Shaded" def setDisplayMode(self,mode): """將attach中定義的顯示模式映射到getDisplayModes中定義的那些。 因為它們具有相同的名稱,所以不需要做任何事情。這個方法是可選的 Map the display mode defined in attach with those defined in getDisplayModes. Since they have the same names nothing needs to be done. This method is optional""" return mode def onChanged(self, vp, prop): """這里我們可以做一些事情,當一個屬性被改變Here we can do something when a single property got changed""" FreeCAD.Console.PrintMessage("Change property: " + str(prop) + " ") if prop == "Color": c = vp.getPropertyByName("Color") self.color.rgb.setValue(c[0],c[1],c[2]) def getIcon(self): """返回XPM格式的圖標,該圖標將顯示在樹形視圖中。此方法是 optional,如果未定義,則顯示默認圖標。 Return the icon in XPM format which will appear in the tree view. This method is optional and if not defined a default icon is shown.""" return """ /* XPM */ static const char * ViewProviderBox_xpm[] = { "16 16 6 1", " c None", ". c #141010", "+ c #615BD2", "@ c #C39D55", "# c #000000", "$ c #57C355", " ........", " ......++..+..", " .@@@@.++..++.", " .@@@@.++..++.", " .@@ .++++++.", " ..@@ .++..++.", "###@@@@ .++..++.", "##$.@@$#.++++++.", "#$#$.$$$........", "#$$####### ", "#$$#$$$$$# ", "#$$#$$$$$# ", "#$$#$$$$$# ", " #$#$$$$$# ", " ##$$$$$# ", " ####### "}; """ def __getstate__(self): """保存文檔時,使用Python的json模塊存儲此對象。 返回所有可序列化對象的元組或無。 When saving the document this object gets stored using Python"s json module. Since we have some un-serializable parts here -- the Coin stuff -- we must define this method to return a tuple of all serializable objects or None.""" return None def __setstate__(self,state): """當從文檔恢復序列化對象時,我們有機會在這里設置一些內部。 因為沒有數據被序列化這里沒有什么需要做的。 When restoring the serialized object from document we have the chance to set some internals here. Since no data were serialized nothing needs to be done here.""" return None def makeBox(): FreeCAD.newDocument() a=FreeCAD.ActiveDocument.addObject("App::FeaturePython","Box") Box(a) ViewProviderBox(a.ViewObject) makeBox()可用的屬性
屬性是FeaturePython對象的真正構建元素。通過它們,用戶將能夠交互和修改您的對象。在文檔中創建新的FeaturePython對象(obj = FreeCAD.ActiveDocument.addObject(“App :: FeaturePython”,“Box”))后,您可以通過發出以下命令獲取可用屬性的列表:
obj.supportedProperties()
您將獲得可用屬性的列表:
App :: PropertyBool App :: PropertyBoolList App :: PropertyFloat App :: PropertyFloatList App :: PropertyFloatConstraint App :: PropertyQuantity App :: PropertyQuantityConstraint App :: PropertyAngle App :: PropertyDistance App :: PropertyLength App :: PropertySpeed App :: PropertyAcceleration App: :PropertyForce App :: PropertyPressure App :: PropertyInteger App :: PropertyIntegerConstraint App :: PropertyPercent App :: PropertyEnumeration App :: PropertyIntegerList App :: PropertyIntegerSet App :: PropertyMap App :: PropertyString App :: PropertyUUID App :: PropertyFont App :: PropertyStringList App :: PropertyLink App :: PropertyLinkSub App :: PropertyLinkList App :: PropertyLinkSubList App :: PropertyMatrix App :: PropertyVector App :: PropertyVectorList App :: PropertyPlacement App :: PropertyPlacementLink App :: PropertyColor App :: PropertyColorList App: :PropertyMaterial App :: PropertyPath App :: PropertyFile App :: PropertyFileIncluded App :: PropertyPythonObject Part :: PropertyPartShape Part :: PropertyGeometryList Part :: PropertyShapeHistory Part :: PropertyFilletEdges Sketcher :: PropertyConstraintList
向自定義對象添加屬性時,請注意以下事項:
不要在屬性描述中使用字符“<”或“>”(這會破壞.fcstd文件中的xml片段)
屬性按字母順序存儲在.fcstd文件中。如果屬性中有形狀,則按字母順序在“Shape”之后的任何屬性將在形狀之后加載,這可能會導致奇怪的行為。
默認情況下,可以更新屬性。可以使屬性為只讀,例如在想要顯示方法結果的情況下。也可以隱藏酒店。可以使用設置屬性類型
obj.setEditorMode(“MyPropertyName”,mode)
其中mode是一個short int,可以設置為:
0 - 默認模式,讀寫 1 - 只讀 2 - 隱藏
在FreeCAD文件重新加載時未設置EditorModes。這可以通過__setstate__函數完成。請參閱http://forum.freecadweb.org/v...。通過使用setEditorMode,屬性僅在PropertyEditor中讀取。它們仍然可以從python中更改。要真正使它們只讀,必須直接在addProperty函數內傳遞設置。有關示例,請參見http://forum.freecadweb.org/v...。
此示例使用“ 零件模塊”創建八面體,然后使用“關鍵”創建其硬幣表示。
首先是Document對象本身:
import FreeCAD, FreeCADGui, Part import pivy from pivy import coin class Octahedron: def __init__(self, obj): "Add some custom properties to our box feature" obj.addProperty("App::PropertyLength","Length","Octahedron","Length of the octahedron").Length=1.0 obj.addProperty("App::PropertyLength","Width","Octahedron","Width of the octahedron").Width=1.0 obj.addProperty("App::PropertyLength","Height","Octahedron", "Height of the octahedron").Height=1.0 obj.addProperty("Part::PropertyPartShape","Shape","Octahedron", "Shape of the octahedron") obj.Proxy = self def execute(self, fp): # Define six vetices for the shape v1 = FreeCAD.Vector(0,0,0) v2 = FreeCAD.Vector(fp.Length,0,0) v3 = FreeCAD.Vector(0,fp.Width,0) v4 = FreeCAD.Vector(fp.Length,fp.Width,0) v5 = FreeCAD.Vector(fp.Length/2,fp.Width/2,fp.Height/2) v6 = FreeCAD.Vector(fp.Length/2,fp.Width/2,-fp.Height/2) # Make the wires/faces f1 = self.make_face(v1,v2,v5) f2 = self.make_face(v2,v4,v5) f3 = self.make_face(v4,v3,v5) f4 = self.make_face(v3,v1,v5) f5 = self.make_face(v2,v1,v6) f6 = self.make_face(v4,v2,v6) f7 = self.make_face(v3,v4,v6) f8 = self.make_face(v1,v3,v6) shell=Part.makeShell([f1,f2,f3,f4,f5,f6,f7,f8]) solid=Part.makeSolid(shell) fp.Shape = solid # helper mehod to create the faces def make_face(self,v1,v2,v3): wire = Part.makePolygon([v1,v2,v3,v1]) face = Part.Face(wire) return face Then, we have the view provider object, responsible for showing the object in the 3D scene: class ViewProviderOctahedron: def __init__(self, obj): "Set this object to the proxy object of the actual view provider" obj.addProperty("App::PropertyColor","Color","Octahedron","Color of the octahedron").Color=(1.0,0.0,0.0) obj.Proxy = self def attach(self, obj): "Setup the scene sub-graph of the view provider, this method is mandatory" self.shaded = coin.SoGroup() self.wireframe = coin.SoGroup() self.scale = coin.SoScale() self.color = coin.SoBaseColor() self.data=coin.SoCoordinate3() self.face=coin.SoIndexedLineSet() self.shaded.addChild(self.scale) self.shaded.addChild(self.color) self.shaded.addChild(self.data) self.shaded.addChild(self.face) obj.addDisplayMode(self.shaded,"Shaded"); style=coin.SoDrawStyle() style.style = coin.SoDrawStyle.LINES self.wireframe.addChild(style) self.wireframe.addChild(self.scale) self.wireframe.addChild(self.color) self.wireframe.addChild(self.data) self.wireframe.addChild(self.face) obj.addDisplayMode(self.wireframe,"Wireframe"); self.onChanged(obj,"Color") def updateData(self, fp, prop): "If a property of the handled feature has changed we have the chance to handle this here" # fp is the handled feature, prop is the name of the property that has changed if prop == "Shape": s = fp.getPropertyByName("Shape") self.data.point.setNum(6) cnt=0 for i in s.Vertexes: self.data.point.set1Value(cnt,i.X,i.Y,i.Z) cnt=cnt+1 self.face.coordIndex.set1Value(0,0) self.face.coordIndex.set1Value(1,1) self.face.coordIndex.set1Value(2,2) self.face.coordIndex.set1Value(3,-1) self.face.coordIndex.set1Value(4,1) self.face.coordIndex.set1Value(5,3) self.face.coordIndex.set1Value(6,2) self.face.coordIndex.set1Value(7,-1) self.face.coordIndex.set1Value(8,3) self.face.coordIndex.set1Value(9,4) self.face.coordIndex.set1Value(10,2) self.face.coordIndex.set1Value(11,-1) self.face.coordIndex.set1Value(12,4) self.face.coordIndex.set1Value(13,0) self.face.coordIndex.set1Value(14,2) self.face.coordIndex.set1Value(15,-1) self.face.coordIndex.set1Value(16,1) self.face.coordIndex.set1Value(17,0) self.face.coordIndex.set1Value(18,5) self.face.coordIndex.set1Value(19,-1) self.face.coordIndex.set1Value(20,3) self.face.coordIndex.set1Value(21,1) self.face.coordIndex.set1Value(22,5) self.face.coordIndex.set1Value(23,-1) self.face.coordIndex.set1Value(24,4) self.face.coordIndex.set1Value(25,3) self.face.coordIndex.set1Value(26,5) self.face.coordIndex.set1Value(27,-1) self.face.coordIndex.set1Value(28,0) self.face.coordIndex.set1Value(29,4) self.face.coordIndex.set1Value(30,5) self.face.coordIndex.set1Value(31,-1) def getDisplayModes(self,obj): "Return a list of display modes." modes=[] modes.append("Shaded") modes.append("Wireframe") return modes def getDefaultDisplayMode(self): "Return the name of the default display mode. It must be defined in getDisplayModes." return "Shaded" def setDisplayMode(self,mode): return mode def onChanged(self, vp, prop): "Here we can do something when a single property got changed" FreeCAD.Console.PrintMessage("Change property: " + str(prop) + " ") if prop == "Color": c = vp.getPropertyByName("Color") self.color.rgb.setValue(c[0],c[1],c[2]) def getIcon(self): return """ /* XPM */ static const char * ViewProviderBox_xpm[] = { "16 16 6 1", " c None", ". c #141010", "+ c #615BD2", "@ c #C39D55", "# c #000000", "$ c #57C355", " ........", " ......++..+..", " .@@@@.++..++.", " .@@@@.++..++.", " .@@ .++++++.", " ..@@ .++..++.", "###@@@@ .++..++.", "##$.@@$#.++++++.", "#$#$.$$$........", "#$$####### ", "#$$#$$$$$# ", "#$$#$$$$$# ", "#$$#$$$$$# ", " #$#$$$$$# ", " ##$$$$$# ", " ####### "}; """ def __getstate__(self): return None def __setstate__(self,state): return None
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/43904.html
摘要:在控制臺中,您可以逐個編寫命令,這些命令在按下時執行宏可以包含由多行組成的更復雜的腳本,只有在執行宏時才會執行。更好的是,您可以在中設置一個選項,以在控制臺中顯示腳本命令。 Python是一種編程語言,使用起來非常簡單,學習起來非常快。它是開源的,多平臺的,可以單獨用于各種各樣的事情,從簡單的shell腳本編程到非常復雜的程序。但其最廣泛的用途之一是作為腳本語言,因為它很容易嵌入到其他...
摘要:中的腳本從頭開始構建,完全由腳本控制。因此,可能是目前可用的最深度可定制的工程應用程序之一。但中的腳本編寫是一種快速查看高級用戶通常是熟悉編程的用戶開發的新功能的方法。 FreeCAD中的Python腳本 FreeCAD從頭開始構建,完全由Python腳本控制。FreeCAD的幾乎所有部分,例如界面,場景內容,甚至3D視圖中此內容的表示,都可以從內置的Python解釋器或您自己的腳本中...
閱讀 1176·2023-04-26 00:34
閱讀 3348·2023-04-25 16:47
閱讀 2110·2021-11-24 11:14
閱讀 3093·2021-09-26 09:55
閱讀 3685·2019-08-30 15:56
閱讀 3211·2019-08-29 16:57
閱讀 1903·2019-08-26 13:38
閱讀 2663·2019-08-26 12:22