Using two Python Addin Combo Boxes to choose feature class first then field from chosen feature class?
Clash Royale CLAN TAG#URR8PPP
up vote
2
down vote
favorite
Last night a student from my Udemy course about writing Python AddIns asked for:
some tips for using a combo box to filter another combo box. What I am
trying to do is use a combo box to select my [feature class], which I've managed
to do. Once that combo box is selected, I want the second box to show
all the fields in that [feature class], which I can then go ahead and select to
perform further analysis on.
I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for TestCombo_addin.combobox (ComboBox)"""
def __init__(self):
self.items = ["cb1item1", "cb1item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
ComboBoxClass1._hook=self
def onSelChange(self, selection):
pass
class ComboBoxClass2(object):
"""Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
def __init__(self):
self.items = ["cb2item1", "cb2item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
def onSelChange(self, selection):
ComboBoxClass1._hook.items.append(selection)
but how do I use the _hook
property of a ComboBoxClass to achieve what my student has asked for?
arcpy python-addin combo-box
add a comment |Â
up vote
2
down vote
favorite
Last night a student from my Udemy course about writing Python AddIns asked for:
some tips for using a combo box to filter another combo box. What I am
trying to do is use a combo box to select my [feature class], which I've managed
to do. Once that combo box is selected, I want the second box to show
all the fields in that [feature class], which I can then go ahead and select to
perform further analysis on.
I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for TestCombo_addin.combobox (ComboBox)"""
def __init__(self):
self.items = ["cb1item1", "cb1item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
ComboBoxClass1._hook=self
def onSelChange(self, selection):
pass
class ComboBoxClass2(object):
"""Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
def __init__(self):
self.items = ["cb2item1", "cb2item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
def onSelChange(self, selection):
ComboBoxClass1._hook.items.append(selection)
but how do I use the _hook
property of a ComboBoxClass to achieve what my student has asked for?
arcpy python-addin combo-box
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
Last night a student from my Udemy course about writing Python AddIns asked for:
some tips for using a combo box to filter another combo box. What I am
trying to do is use a combo box to select my [feature class], which I've managed
to do. Once that combo box is selected, I want the second box to show
all the fields in that [feature class], which I can then go ahead and select to
perform further analysis on.
I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for TestCombo_addin.combobox (ComboBox)"""
def __init__(self):
self.items = ["cb1item1", "cb1item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
ComboBoxClass1._hook=self
def onSelChange(self, selection):
pass
class ComboBoxClass2(object):
"""Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
def __init__(self):
self.items = ["cb2item1", "cb2item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
def onSelChange(self, selection):
ComboBoxClass1._hook.items.append(selection)
but how do I use the _hook
property of a ComboBoxClass to achieve what my student has asked for?
arcpy python-addin combo-box
Last night a student from my Udemy course about writing Python AddIns asked for:
some tips for using a combo box to filter another combo box. What I am
trying to do is use a combo box to select my [feature class], which I've managed
to do. Once that combo box is selected, I want the second box to show
all the fields in that [feature class], which I can then go ahead and select to
perform further analysis on.
I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for TestCombo_addin.combobox (ComboBox)"""
def __init__(self):
self.items = ["cb1item1", "cb1item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
ComboBoxClass1._hook=self
def onSelChange(self, selection):
pass
class ComboBoxClass2(object):
"""Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
def __init__(self):
self.items = ["cb2item1", "cb2item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
def onSelChange(self, selection):
ComboBoxClass1._hook.items.append(selection)
but how do I use the _hook
property of a ComboBoxClass to achieve what my student has asked for?
arcpy python-addin combo-box
arcpy python-addin combo-box
edited 5 hours ago
asked 5 hours ago
PolyGeoâ¦
52.3k1779236
52.3k1779236
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
2
down vote
The code that I used to solve this was:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
ComboBoxClass2._hook=self
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
To understand the code:
- when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.
- when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using
ComboBoxClass2._hook=self
- when I choose a shapefile from the first combo box its
onSelChange
function takes myselection
and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. SinceListFields
returns a list of field objects I use list comprehension to turn that into a list of field names instead.
I'm currently doing something similar but using global variables instead of aClass._hook
. I think I like the way you've done it better. But could you please explain the._hook
a bit further. Ie, is_hook
just an arbitrarily named class property that you made up, or is it a built-in Python name?
â Son of a Beach
5 hours ago
@SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
â PolyGeoâ¦
5 hours ago
What happens if you replace._hook
with something arbitrary like,.sharedInstance
? (If you have a chance to try it out.) I can't find any documentation on_hook
, and the only examples I can find for it make it look like it's just an arbitrary property.
â Son of a Beach
4 hours ago
@SonofaBeach You're right. I replaced._hook
with.sharedInstance
and it worked just the same.
â PolyGeoâ¦
4 hours ago
Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
â Son of a Beach
4 hours ago
add a comment |Â
up vote
0
down vote
I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.
What I do is use the instances of the classes, not the classes themselves.
For example, in config.xml
you will have something like:
<?xml version="1.0"?>
<ESRI.Configuration etc...>
<etc...>
<AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
<ArcMap>
<Commands>
<ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
<ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
</Commands>
<Extensions></Extensions>
<Toolbars>
<Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
<Items>
<ComboBox refID="ComboBox_addin.combobox1"/>
<ComboBox refID="ComboBox_addin.combobox2"/>
</Items>
</Toolbar>
</Toolbars>
<Menus></Menus>
</ArcMap>
</AddIn>
</ESRI.Configuration>
Note the id
and refID
are the same. These will refer to instances of these classes.
Then you just replace references to ComboBoxClass2
to combobox2
in your code:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
If you run into a NameError
(an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
:
##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
combobox1 = ComboBoxClass1()
combobox2 = ComboBoxClass2()
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
The code that I used to solve this was:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
ComboBoxClass2._hook=self
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
To understand the code:
- when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.
- when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using
ComboBoxClass2._hook=self
- when I choose a shapefile from the first combo box its
onSelChange
function takes myselection
and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. SinceListFields
returns a list of field objects I use list comprehension to turn that into a list of field names instead.
I'm currently doing something similar but using global variables instead of aClass._hook
. I think I like the way you've done it better. But could you please explain the._hook
a bit further. Ie, is_hook
just an arbitrarily named class property that you made up, or is it a built-in Python name?
â Son of a Beach
5 hours ago
@SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
â PolyGeoâ¦
5 hours ago
What happens if you replace._hook
with something arbitrary like,.sharedInstance
? (If you have a chance to try it out.) I can't find any documentation on_hook
, and the only examples I can find for it make it look like it's just an arbitrary property.
â Son of a Beach
4 hours ago
@SonofaBeach You're right. I replaced._hook
with.sharedInstance
and it worked just the same.
â PolyGeoâ¦
4 hours ago
Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
â Son of a Beach
4 hours ago
add a comment |Â
up vote
2
down vote
The code that I used to solve this was:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
ComboBoxClass2._hook=self
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
To understand the code:
- when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.
- when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using
ComboBoxClass2._hook=self
- when I choose a shapefile from the first combo box its
onSelChange
function takes myselection
and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. SinceListFields
returns a list of field objects I use list comprehension to turn that into a list of field names instead.
I'm currently doing something similar but using global variables instead of aClass._hook
. I think I like the way you've done it better. But could you please explain the._hook
a bit further. Ie, is_hook
just an arbitrarily named class property that you made up, or is it a built-in Python name?
â Son of a Beach
5 hours ago
@SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
â PolyGeoâ¦
5 hours ago
What happens if you replace._hook
with something arbitrary like,.sharedInstance
? (If you have a chance to try it out.) I can't find any documentation on_hook
, and the only examples I can find for it make it look like it's just an arbitrary property.
â Son of a Beach
4 hours ago
@SonofaBeach You're right. I replaced._hook
with.sharedInstance
and it worked just the same.
â PolyGeoâ¦
4 hours ago
Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
â Son of a Beach
4 hours ago
add a comment |Â
up vote
2
down vote
up vote
2
down vote
The code that I used to solve this was:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
ComboBoxClass2._hook=self
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
To understand the code:
- when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.
- when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using
ComboBoxClass2._hook=self
- when I choose a shapefile from the first combo box its
onSelChange
function takes myselection
and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. SinceListFields
returns a list of field objects I use list comprehension to turn that into a list of field names instead.
The code that I used to solve this was:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
ComboBoxClass2._hook=self
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
To understand the code:
- when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.
- when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using
ComboBoxClass2._hook=self
- when I choose a shapefile from the first combo box its
onSelChange
function takes myselection
and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. SinceListFields
returns a list of field objects I use list comprehension to turn that into a list of field names instead.
edited 11 mins ago
Luke
27.9k251101
27.9k251101
answered 5 hours ago
PolyGeoâ¦
52.3k1779236
52.3k1779236
I'm currently doing something similar but using global variables instead of aClass._hook
. I think I like the way you've done it better. But could you please explain the._hook
a bit further. Ie, is_hook
just an arbitrarily named class property that you made up, or is it a built-in Python name?
â Son of a Beach
5 hours ago
@SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
â PolyGeoâ¦
5 hours ago
What happens if you replace._hook
with something arbitrary like,.sharedInstance
? (If you have a chance to try it out.) I can't find any documentation on_hook
, and the only examples I can find for it make it look like it's just an arbitrary property.
â Son of a Beach
4 hours ago
@SonofaBeach You're right. I replaced._hook
with.sharedInstance
and it worked just the same.
â PolyGeoâ¦
4 hours ago
Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
â Son of a Beach
4 hours ago
add a comment |Â
I'm currently doing something similar but using global variables instead of aClass._hook
. I think I like the way you've done it better. But could you please explain the._hook
a bit further. Ie, is_hook
just an arbitrarily named class property that you made up, or is it a built-in Python name?
â Son of a Beach
5 hours ago
@SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
â PolyGeoâ¦
5 hours ago
What happens if you replace._hook
with something arbitrary like,.sharedInstance
? (If you have a chance to try it out.) I can't find any documentation on_hook
, and the only examples I can find for it make it look like it's just an arbitrary property.
â Son of a Beach
4 hours ago
@SonofaBeach You're right. I replaced._hook
with.sharedInstance
and it worked just the same.
â PolyGeoâ¦
4 hours ago
Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
â Son of a Beach
4 hours ago
I'm currently doing something similar but using global variables instead of a
Class._hook
. I think I like the way you've done it better. But could you please explain the ._hook
a bit further. Ie, is _hook
just an arbitrarily named class property that you made up, or is it a built-in Python name?â Son of a Beach
5 hours ago
I'm currently doing something similar but using global variables instead of a
Class._hook
. I think I like the way you've done it better. But could you please explain the ._hook
a bit further. Ie, is _hook
just an arbitrarily named class property that you made up, or is it a built-in Python name?â Son of a Beach
5 hours ago
@SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
â PolyGeoâ¦
5 hours ago
@SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
â PolyGeoâ¦
5 hours ago
What happens if you replace
._hook
with something arbitrary like, .sharedInstance
? (If you have a chance to try it out.) I can't find any documentation on _hook
, and the only examples I can find for it make it look like it's just an arbitrary property.â Son of a Beach
4 hours ago
What happens if you replace
._hook
with something arbitrary like, .sharedInstance
? (If you have a chance to try it out.) I can't find any documentation on _hook
, and the only examples I can find for it make it look like it's just an arbitrary property.â Son of a Beach
4 hours ago
@SonofaBeach You're right. I replaced
._hook
with .sharedInstance
and it worked just the same.â PolyGeoâ¦
4 hours ago
@SonofaBeach You're right. I replaced
._hook
with .sharedInstance
and it worked just the same.â PolyGeoâ¦
4 hours ago
Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
â Son of a Beach
4 hours ago
Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
â Son of a Beach
4 hours ago
add a comment |Â
up vote
0
down vote
I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.
What I do is use the instances of the classes, not the classes themselves.
For example, in config.xml
you will have something like:
<?xml version="1.0"?>
<ESRI.Configuration etc...>
<etc...>
<AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
<ArcMap>
<Commands>
<ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
<ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
</Commands>
<Extensions></Extensions>
<Toolbars>
<Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
<Items>
<ComboBox refID="ComboBox_addin.combobox1"/>
<ComboBox refID="ComboBox_addin.combobox2"/>
</Items>
</Toolbar>
</Toolbars>
<Menus></Menus>
</ArcMap>
</AddIn>
</ESRI.Configuration>
Note the id
and refID
are the same. These will refer to instances of these classes.
Then you just replace references to ComboBoxClass2
to combobox2
in your code:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
If you run into a NameError
(an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
:
##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
combobox1 = ComboBoxClass1()
combobox2 = ComboBoxClass2()
add a comment |Â
up vote
0
down vote
I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.
What I do is use the instances of the classes, not the classes themselves.
For example, in config.xml
you will have something like:
<?xml version="1.0"?>
<ESRI.Configuration etc...>
<etc...>
<AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
<ArcMap>
<Commands>
<ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
<ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
</Commands>
<Extensions></Extensions>
<Toolbars>
<Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
<Items>
<ComboBox refID="ComboBox_addin.combobox1"/>
<ComboBox refID="ComboBox_addin.combobox2"/>
</Items>
</Toolbar>
</Toolbars>
<Menus></Menus>
</ArcMap>
</AddIn>
</ESRI.Configuration>
Note the id
and refID
are the same. These will refer to instances of these classes.
Then you just replace references to ComboBoxClass2
to combobox2
in your code:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
If you run into a NameError
(an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
:
##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
combobox1 = ComboBoxClass1()
combobox2 = ComboBoxClass2()
add a comment |Â
up vote
0
down vote
up vote
0
down vote
I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.
What I do is use the instances of the classes, not the classes themselves.
For example, in config.xml
you will have something like:
<?xml version="1.0"?>
<ESRI.Configuration etc...>
<etc...>
<AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
<ArcMap>
<Commands>
<ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
<ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
</Commands>
<Extensions></Extensions>
<Toolbars>
<Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
<Items>
<ComboBox refID="ComboBox_addin.combobox1"/>
<ComboBox refID="ComboBox_addin.combobox2"/>
</Items>
</Toolbar>
</Toolbars>
<Menus></Menus>
</ArcMap>
</AddIn>
</ESRI.Configuration>
Note the id
and refID
are the same. These will refer to instances of these classes.
Then you just replace references to ComboBoxClass2
to combobox2
in your code:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
If you run into a NameError
(an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
:
##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
combobox1 = ComboBoxClass1()
combobox2 = ComboBoxClass2()
I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.
What I do is use the instances of the classes, not the classes themselves.
For example, in config.xml
you will have something like:
<?xml version="1.0"?>
<ESRI.Configuration etc...>
<etc...>
<AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
<ArcMap>
<Commands>
<ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
<ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
</Commands>
<Extensions></Extensions>
<Toolbars>
<Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
<Items>
<ComboBox refID="ComboBox_addin.combobox1"/>
<ComboBox refID="ComboBox_addin.combobox2"/>
</Items>
</Toolbar>
</Toolbars>
<Menus></Menus>
</ArcMap>
</AddIn>
</ESRI.Configuration>
Note the id
and refID
are the same. These will refer to instances of these classes.
Then you just replace references to ComboBoxClass2
to combobox2
in your code:
import arcpy
import pythonaddins
class ComboBoxClass1(object):
"""Implementation for ComboBox_addin.combobox1 (ComboBox)"""
def __init__(self):
arcpy.env.workspace = r"C:polygeoQGIS"
self.items = arcpy.ListFeatureClasses()
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
def onSelChange(self, selection):
combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
class ComboBoxClass2(object):
"""Implementation for ComboBox_addin.combobox2 (ComboBox)"""
def __init__(self):
self.items =
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWWWWWWWW'
self.width = 'WWWWWWWWWWWW'
def onSelChange(self, selection):
pass
def onEditChange(self, text):
pass
def onFocus(self, focused):
pass
def onEnter(self):
pass
def refresh(self):
pass
If you run into a NameError
(an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
:
##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
combobox1 = ComboBoxClass1()
combobox2 = ComboBoxClass2()
edited 3 hours ago
answered 3 hours ago
Luke
27.9k251101
27.9k251101
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f300756%2fusing-two-python-addin-combo-boxes-to-choose-feature-class-first-then-field-from%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password