Python Add-In combobox.value attribute getting deleted somehow

6775
3
08-11-2014 09:16 AM
CalebMackey1
Regular Contributor II

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}\LineAngles_addin.py", 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

sys.path.append(r'\\Arcserver1\GIS\_Resources\ESRI\Python\BMI_Library')

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()

    array.add(ext.lowerLeft)

    array.add(ext.lowerRight)

    array.add(ext.upperRight)

    array.add(ext.upperLeft)

    array.add(ext.lowerLeft)

    return arcpy.Polygon(array, sr)

def get_angle(xy1, xy2):

    """Calculate azimuth angle from two points. (Zero is north.)"""

    # function courtesy of Curtis Price

    try:

        # ArcPy point objects

        x1, y1, x2, y2 = xy1.X, xy1.Y, xy2.X, xy2.Y

    except:

        # 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 = [l.name 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

        pass

0 Kudos
3 Replies
JasonScheirer
Regular Contributor II

If it were an ArcGIS installation issue it's likely to show up as the add-in not working at all.

Try setting self.value = 'something' in the combobox's __init__. It might just be because it's not initialized, there's no reason it'd ever get deleted.

CalebMackey1
Regular Contributor II

Thanks Jason, that sounded promising but it did not work.  I added a dummy variable to the combobox init, re-ran the makeaddin.py, and re-installed it.  To my surprise, the value attribute still did not show up.

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

        self.value = 'something' #dummy variable

in my dir(combobox) return, value is still missing.  I have been having really strange issues on my VM lately so I'm hoping it is something related to that.  A coworker is running 10.2 on his normal machine (I still have to run 10.0 on my normal machine until we finish up our server upgrade) and stuff works on his machine that fails on my VM.  If you want to take a look at it, I can email you the add-in.

0 Kudos
CalebMackey1
Regular Contributor II

I forgot to post this, but I resolved the issue by changing using self in the onFocus method code to this:

def onFocus(self, focused):

        if focused:

            self.mxd = arcpy.mapping.MapDocument('current')

            self.df = self.mxd.activeDataFrame

            lyrs = [l.name for l in arcpy.mapping.ListLayers(self.mxd, '*', self.df)

                    if not l.isBroken and l.isFeatureLayer and

                    arcpy.Describe(l).shapeType == 'Polyline']

            self.items = sorted(lyrs)

            del self.mxd

0 Kudos