1

I have created a minimalist test Python AddIn using ArcGIS 10.4.1 for Desktop, with a toolbar and two comboboxes on it.

The code (TestAddIn_addin.py and config.xml) appears at the bottom of this question and when installed its interface is as below:

enter image description here

Clicking the down arrowhead next to:

  • ComboBox1 offers two choices: item1 and item2
  • ComboBox1 offers two choices: item3 and item4

This is a simplification of what I am wanting to do in practice, but in the test when I choose either item1 or item2 from ComboBox1 I want its onSelChange event to change the choices offered by ComboBoxClass2 to be A, B and C. The piece of code to do just that in the ComboBoxClass1 class is:

def onSelChange(self, selection):
    ComboBoxClass2.items = ["A","B","C"]
    ComboBoxClass2.refresh()

The above would seem to match the answer to Refreshing Combobox of Python Add-in of ArcPy?

However, when I test this Python AddIn from ArcMap with the Python window open I get an error:

Traceback (most recent call last): File "C:\Users\PolyGeo\AppData\Local\ESRI\Desktop10.4\AssemblyCache{EE92FFB8-6EED-46E8-83CC-6E8DD8A293BA}\TestAddIn_addin.py", line 14, in onSelChange ComboBoxClass2.refresh() TypeError: unbound method refresh() must be called with ComboBoxClass2 instance as first argument (got nothing instead)

It seems to want me to pass a value into ComboBoxClass2.refresh() and I have experimented with various stabs in the dark like ComboBoxClass2.refresh(self), ComboBoxClass2.refresh(ComboBoxClass2) and ComboBoxClass2.refresh(TestAddIn_addin.combobox1) but these only succeed in similar errors from the same line of code.

Does anyone know what value ComboBoxClass2.refresh() might be expecting as a parameter here?

ComboBoxClass2.refresh(self) moves the error to:

Traceback (most recent call last): File "C:\Users\PolyGeo\AppData\Local\ESRI\Desktop10.4\AssemblyCache{EE92FFB8-6EED-46E8-83CC-6E8DD8A293BA}\TestAddIn_addin.py", line 14, in onSelChange ComboBoxClass2.refresh(self) TypeError: unbound method refresh() must be called with ComboBoxClass2 instance as first argument (got ComboBoxClass1 instance instead)

C:\Temp\TestAddIn\Install\TestAddIn_addin.py:

import arcpy
import pythonaddins

class ComboBoxClass1(object):
    """Implementation for TestAddIn_addin.combobox1 (ComboBox)"""
    def __init__(self):
        self.items = ["item1", "item2"]
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWW'
        self.width = 'WWWWWW'
    def onSelChange(self, selection):
        ComboBoxClass2.items = ["A","B","C"]
        ComboBoxClass2.refresh()
    def onEditChange(self, text):
        pass
    def onFocus(self, focused):
        pass
    def onEnter(self):
        pass
    def refresh(self):
        pass

class ComboBoxClass2(object):
    """Implementation for TestAddIn_addin.combobox2 (ComboBox)"""
    def __init__(self):
        self.items = ["item3", "item4"]
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWW'
        self.width = 'WWWWWW'
    def onSelChange(self, selection):
        pass
    def onEditChange(self, text):
        pass
    def onFocus(self, focused):
        pass
    def onEnter(self):
        pass
    def refresh(self):
        pass

C:\Temp\TestAddIn\config.xml:

<ESRI.Configuration xmlns="http://schemas.esri.com/Desktop/AddIns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Name>Python Addin</Name><AddInID>{ee92ffb8-6eed-46e8-83cc-6e8dd8a293ba}</AddInID><Description>New Addin</Description><Version>0.1</Version><Image /><Author>Untitled</Author><Company>Untitled</Company><Date>09/02/2016</Date><Targets><Target name="Desktop" version="10.1" /></Targets><AddIn language="PYTHON" library="TestAddIn_addin.py" namespace="TestAddIn_addin"><ArcMap>
    <Commands>
        <ComboBox caption="ComboBox1" category="Python Addin" class="ComboBoxClass1" id="TestAddIn_addin.combobox1" itemSizeString="WWWWWW" message="" rows="4" sizeString="WWWWWW" tip=""><Help heading="" /></ComboBox>
        <ComboBox caption="ComboBox2" category="Python Addin" class="ComboBoxClass2" id="TestAddIn_addin.combobox2" itemSizeString="WWWWWW" message="" rows="4" sizeString="WWWWWW" tip=""><Help heading="" /></ComboBox>
        </Commands>
    <Extensions>
        </Extensions>
    <Toolbars>
        <Toolbar caption="Toolbar" category="Python Addin" id="TestAddIn_addin.toolbar" showInitially="true"><Items><ComboBox refID="TestAddIn_addin.combobox1" /><ComboBox refID="TestAddIn_addin.combobox2" /></Items></Toolbar>
        </Toolbars>
    <Menus>
        </Menus>
    </ArcMap></AddIn></ESRI.Configuration>
  • 1
    ComboBoxClass2 is a class name not the instance itself. You will need to some how get the instance of the combobox that ArcGIS is making. – Nathan W Sep 2 '16 at 5:16
  • 1
    I suspect you will have to get a instance to the other combo using it's ID? – Nathan W Sep 2 '16 at 5:18
  • 1
    Looks like you might need to use a global ;) – Nathan W Sep 2 '16 at 5:21
  • @NathanW I tried the ID from config.xml but ComboBoxClass2.refresh("TestAddIn_addin.combobox2") led to Traceback (most recent call last): File "C:\Users\PolyGeo\AppData\Local\ESRI\Desktop10.4\AssemblyCache\{EE92FFB8-6EED-46E8-83CC-6E8DD8A293BA}\TestAddIn_addin.py", line 14, in onSelChange ComboBoxClass2.refresh("TestAddIn_addin.combobox2") TypeError: unbound method refresh() must be called with ComboBoxClass2 instance as first argument (got str instance instead) – PolyGeo Sep 2 '16 at 5:31
  • 1
    You can't call ComboBoxClass2.refersh() because ComboBoxClass2 is a name of a type not the instance. I suspect you will need to make a global and store ComboBoxClass2 in there in it's init method. – Nathan W Sep 2 '16 at 5:35
1

To get this to work I appended two lines of code to the __init__ function of class ComboBoxClass2:

class ComboBoxClass2(object):
    """Implementation for TestAddIn_addin.combobox2 (ComboBox)"""
    def __init__(self):
        self.items = ["item3", "item4"]
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWW'
        self.width = 'WWWWWW'

so that it became:

class ComboBoxClass2(object):
    """Implementation for TestAddIn_addin.combobox2 (ComboBox)"""
    def __init__(self):
        self.items = ["item3", "item4"]
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWW'
        self.width = 'WWWWWW'
        global secondComboBox
        secondComboBox = self

and then in my ComboBoxClass1 class I changed:

def onSelChange(self, selection):
    ComboBoxClass2.items = ["A","B","C"]
    ComboBoxClass2.refresh("TestAddIn_addin.combobox2")

to:

def onSelChange(self, selection):
    secondComboBox.items = ["A","B","C"]
    secondComboBox.refresh()

In other words, and with the help of @NathanW, I made the instance of class ComboBox2 that I was using into a global called secondComboBox and then refreshed that within class ComboBox1.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.