COM objects (arcobjects) in Python
我不熟悉OOP,尝试在Python中使用COM对象(arcObjects)。这个程序与地理信息系统有关,但我没有得到任何关于地理信息系统的答案,所以我在这里问。下面是我的代码。我被困在接收iframelement的最后。ESRI将其描述为抽象类的成员/接口,抽象类本身不能创建对象。我需要将其中包含的信息传递给它的coclass(mapframe)中的对象。
有什么建议吗?
另外,在哪里可以找到Python中对象的名称约定?有p,i作为前缀,我不确定它们来自哪里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | from comtypes.client import CreateObject, GetModule import arcpy def CType(obj, interface): """Casts obj to interface and returns comtypes POINTER or None""" try: newobj = obj.QueryInterface(interface) return newobj except: return None def NewObj(MyClass, MyInterface): """Creates a new comtypes POINTER object where \ MyClass is the class to be instantiated, \ MyInterface is the interface to be assigned""" from comtypes.client import CreateObject try: ptr = CreateObject(MyClass, interface=MyInterface) return ptr except: return None esriCarto = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriCarto.olb") esriCartoUI = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriCartoUI.olb") esriMapUI = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriArcMapUI.olb") esriFrame = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.0\com\esriFramework.olb") arcpy.SetProduct('Arcinfo') pApp = NewObj(esriFrame.AppROT, esriFrame.IAppROT).Item(0) pDoc = pApp.Document pMxDoc = CType(pDoc, esriMapUI.IMxDocument) pLayout = pMxDoc.PageLayout pGraphContLayout = CType(pLayout, esriCarto.IGraphicsContainer) iFrameElement = pGraphContLayout.FindFrame(pMxDoc.ActiveView.FocusMap) |
据我所知,iframeElement是一个抽象类的接口,我需要从它继承属性(指针)到mapframe对象。我该怎么做?它如何通过imapgrids接口到达对象?有什么建议吗?
iframeElement是一个接口,因此不能本身创建它的实例。这个接口是由各种类实现的,包括mapframe,这意味着(在基本术语中)这些对象的一个实例的行为类似于iframeElement。因此,如果从igraphicContainer.findFrame()中获取iframeElement,则可以将其传递给其他需要iframeElement的对象,而无需了解对象的实际类型。
我建议阅读OOP中接口的含义,因为ESRI的代码使用很多接口。
关于命名转换-对于如何命名变量没有严格的快速规则。
从代码的外观来看,p指的是具有不同类型的对象,而i指的是仅由接口定义的对象。但是在那一点上,调用一个与它所引用的接口同名的变量(小写的"i"除外)是一种不好的方法,并且会导致混淆。(国际海事组织)
编辑:回答你的最后一个问题(对不起,我原来错过了):
如果pgraphContLayout.findframe()返回mapframe类型的对象(但不能保证它会返回),那么您应该能够简单地将其强制转换为imapgrids:
1 2 3 | pGraphContLayout = CType(pLayout, esriCarto.IGraphicsContainer) pFrame = pGraphContLayout.FindFrame(pMxDoc.ActiveView.FocusMap) pGrids = CType(pFrame, IMapGrids) |
听起来你可能会被python的抽象基类搞糊涂了,它似乎服务于接口的目的……?这个线程很有用:抽象类和Python中的接口之间的区别