COM-объекты (arcobjects) в Python
Я новичок в ООП и пытаюсь использовать COM-объекты (arcobjects) в Python. Программа связана с ГИС, но я не получил никаких ответов на GIS.SE, поэтому я спрашиваю здесь. Ниже приведен фрагмент моего кода. Я застрял в конце, где я получаю iFrameElement. ESRI описывает его как член / интерфейс Abstract Class, который не может создавать объекты сам. Мне нужно передать содержащуюся в нем информацию объекту в его 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 - это интерфейс, поэтому вы не можете создать его экземпляр как таковой. Этот интерфейс реализуется различными классами, включая MapFrame, что означает (в основных терминах), что экземпляр любого из этих объектов "ведет себя" как IFrameElement. Поэтому, если вы получаете IFrameElement из IGraphicsContainer.FindFrame(), вы можете передать его чему-то другому, ожидающему IFrameElement, без необходимости выяснения, каков фактический тип объекта.
Я бы посоветовал прочитать, что означают интерфейсы в ООП, потому что код ESRI их часто использует.
Что касается именования конвенций - не существует жесткого и быстрого правила о том, как называть ваши переменные.
Судя по вашему коду, p относится к объекту с отличным типом, а i относится к объекту, определенному только интерфейсом. Но на этом замечание, вызов переменной с тем же именем, что и интерфейс, на который она ссылается (за исключением строчной буквы 'i'), является плохим способом выполнения действий и приведет к путанице. (ИМО)
Изменить: Чтобы ответить на ваш последний вопрос (извините, я пропустил его изначально):
Если pGraphContLayout.FindFrame() возвращает объект типа MapFrame (и нет никакой гарантии, что он это сделает), вы можете просто преобразовать его в IMapGrids:
pGraphContLayout = CType(pLayout, esriCarto.IGraphicsContainer)
pFrame = pGraphContLayout.FindFrame(pMxDoc.ActiveView.FocusMap)
pGrids = CType(pFrame, IMapGrids)
Похоже, вас могут запутать абстрактные базовые классы Python, которые, похоже, служат интерфейсам...? Этот поток полезен: Разница между абстрактным классом и интерфейсом в Python