Python 中的 COM 对象(arcobjects)

Posted

技术标签:

【中文标题】Python 中的 COM 对象(arcobjects)【英文标题】:COM objects (arcobjects) in Python 【发布时间】:2012-08-24 19:45:24 【问题描述】:

我是 OOP 的新手,正在尝试在 Python 中使用 COM 对象(arcobjects)。程序与 GIS 相关,但我在 GIS.SE 上没有得到任何答案,所以我在这里问。下面是我的一段代码。我被困在收到 iFrameElement 的最后。 ESRI 将其描述为抽象类的成员/接口,它本身不能创建对象。我需要将其中包含的信息传递给其 CoClass(MapFrame)中的对象。

有什么建议吗?

我在哪里可以找到 Python 中对象的命名约定?有p,i作为前缀,我不确定它们来自哪里。

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\n\
   MyClass is the class to be instantiated,\n\
   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 接口获取对象?有什么建议吗?

【问题讨论】:

【参考方案1】:

IFrameElement 是一个接口,因此您不能创建它本身的实例。此接口由various classes 实现,包括 MapFrame,这意味着(在基本术语中)任何这些对象的实例“行为”都像 IFrameElement。因此,如果您从 IGraphicsContainer.FindFrame() 获得 IFrameElement,则可以将其传递给其他需要 IFrameElement 的对象,而无需找出对象的实际类型。

我建议阅读接口在 OOP 中的含义,因为 ESRI 的代码大量使用

关于命名约定 - 对变量的命名没有硬性规定。

从您的代码看来,p 指的是具有不同类型的对象,而 i 指的是仅由接口定义的对象。但是请注意,以与其引用的接口相同的名称调用变量(小写“i”除外)是一种不好的处理方式,并且会导致混乱。 (海事组织)

编辑: 回答你的最后一个问题(对不起,我最初错过了):

如果 pGraphContLayout.FindFrame() 返回 MapFrame 类型的对象(并且不能保证确实如此),那么您应该能够简单地将其转换为 IMapGrids:

pGraphContLayout = CType(pLayout, esriCarto.IGraphicsContainer)
pFrame = pGraphContLayout.FindFrame(pMxDoc.ActiveView.FocusMap)
pGrids = CType(pFrame, IMapGrids)

听起来您可能对 Python 的抽象基类感到困惑,它们似乎服务于接口的目的......?这个帖子很有用:Difference between abstract class and interface in Python

【讨论】:

同意所有这些(根据我上面的问题)。作为一个初学者,我的问题是,你如何传递这些信息(需要看机制,代码行)。我确实知道如何创建新的 MapFrame 对象 (pMapFrame = NewObj(esriCarto.MapFrame, esriCarto.IMapFrame) 但如何从 IFrameElement 继承信息?大多数示例都是在 VB 或 C# 或 C++ 中,没有具体说明如何进行在 Python 中。谢谢。 @Tomek:更新了我原来的答案。如果你有一个 MapFrame 类型的对象并且你想使用 IFrameElement 中的方法,你只需要将它转换到那个接口:thisFE = CType(pMapFrame, IFrameElement)。 谢谢一百万。而已。事实上,我有点糊涂了。再次感谢。

以上是关于Python 中的 COM 对象(arcobjects)的主要内容,如果未能解决你的问题,请参考以下文章

python中的类型和对象

无法从python中的json数组获取嵌套对象

python中的特殊数据类型

Python 面向对象(下)

2019-04-15 Python中的面向对象学习总结

python中的Iterable对象和Iterator