Python中的COM对象(arcObjects)

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中的接口之间的区别