AnsweredAssumed Answered

Python Add-In combobox.value attribute getting deleted somehow

Question asked by Caleb1987 on Aug 11, 2014
Latest reply on Sep 15, 2014 by Caleb1987

Jason Scheirer - Jason, I mentioned this issue to you at the Esri UC...and well, it happened again.


I'm having a strange issue with creating Python Add-Ins with comboboxes.  I have a pretty simple Python Add-In in which the user can draw a rectangle to select some lines from a specific layer (layer name grabbed from combobox layer list) . By using comtypes and ArcObjects, it will place a text element showing the quadrant bearing of the line at its midpoint in DMS format.  However, I am having an issue where the combox.value attribute is getting deleted somehow.  This has happened before, and to remedy it I had to delete the addin_assistant folder, re-download it and build the Add-In again from scratch.  This fix did not work this time.  There is nothing in my code that would delete the value and my code fails here:


  print dir(combobox)
  layer = combobox.value  #point of failure


And my error:

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'df', 'dropdownWidth', 'editable', 'enabled', 'items', 'onFocus', 'refresh', 'width'] # 'value' attribute is missing here, why?


Traceback (most recent call last):

  File "C:\Users\calebma\AppData\Local\ESRI\Desktop10.2\AssemblyCache\{01396F93-E4C1-35F1-4056-AE2322E49B90}\", line 63, in onRectangle

    layer = combobox.value

AttributeError: 'ComboBoxClass1' object has no attribute 'value'


Has anyone else experienced this?  The problem could be a bad install.  I am running 10.2 on a VM.  This smells like a corrupted DLL somewhere to me.  Here is my full code:


import arcpy
import pythonaddins
import math
import sys
import arcobjects #custom module
from arcobjects import elements 

def makePolyFromExtent(ext, sr):
    '''makes an arcpy polygon object from an input extent object.
    Returns a polygon geometry object.'''
    array = arcpy.Array()
    return arcpy.Polygon(array, sr)

def get_angle(xy1, xy2):
    """Calculate azimuth angle from two points. (Zero is north.)"""
    # function courtesy of Curtis Price
        # ArcPy point objects
        x1, y1, x2, y2 = xy1.X, xy1.Y, xy2.X, xy2.Y
        # xy strings, e.g. "0 0"
        x1, y1 = [float(x) for x in xy1.split()]
        x2, y2 = [float(x) for x in xy2.split()]
        dx, dy = (x2 - x1, y2 - y1)
    return 90 - math.degrees(math.atan2(dy, dx))

def quadrant_bearing(line):
    """returns quadrant bearing in DMS"""
    deg = '\xb0'
    pt1 = line.firstPoint
    pt2 = line.lastPoint
    angle = abs(get_angle(pt1, pt2) - 180)
    d = int(math.floor(angle))
    m_float = (angle - d) * 60.0
    m = int(m_float)
    s = (m_float - m) * 60
    return '{0}{1} {2}\' {3:.2f}"'.format(d,deg,m,s)

def midpoint(point_a, point_b):#, sr):
    x1 = point_a.X
    y1 = point_a.Y
    x2 = point_b.X
    y2 = point_b.Y

    # Find midpoint
    x = (x1 + x2) / 2.0
    y = (y1 + y2) / 2.0
    return (x, y)

class ComboBoxClass1(object):
    """Implementation for LineAngles_addin.combobox (ComboBox)"""
    def __init__(self):
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'W' * 12
        self.width = 'W' * 12
    def onFocus(self, focused):
        if focused:
            mxd = arcpy.mapping.MapDocument('current')
            df = mxd.activeDataFrame
            lyrs = [ for l in arcpy.mapping.ListLayers(mxd, '*', df)
                    if not l.isBroken and l.supports('DATASOURCE')]
            self.items = sorted(lyrs)
            del mxd

class ToolClass3(object):
    """Implementation for LineAngles_addin.tool (Tool)"""
    def __init__(self):
        self.enabled = True
        self.shape = "Rectangle"
        self.cursor = 3
    def onRectangle(self, rectangle_geometry):
        # get spatial reference
        print dir(combobox)
        layer = combobox.value
        mxd = arcpy.mapping.MapDocument('current')
        df = mxd.activeDataFrame
        sr = df.spatialReference

        # make polygon extent object
        poly = makePolyFromExtent(rectangle_geometry, sr)

        # get layer's data type
        lyr = arcpy.mapping.ListLayers(mxd, layer)[0]

        # arcobjects get current app (IApplication interface Pointer)
        pApp = arcobjects.GetCurrentApp()

        # get dms as text
        with arcpy.da.SearchCursor(line, 'SHAPE@') as rows:
            for row in rows:
                dms = quadrant_bearing(row[0])
                # add text element
                x,y = midpoint(row[0].firstPoint, row[0].lastPoint) # to place text element at midpoint of line
                elements.add_text(pApp, text=dms, name='dms', size=12, bold=True, x=x, y=y, view='data') # add text element to data view