Limit combobox results to map extent

4968
12
Jump to solution
03-07-2016 08:37 AM
StevenGraf1
Occasional Contributor III

I'm using this thread as the base for my python addin toolbar.How to populate Add-In Combo Box with attributes

I was wondering if it was possible to limit the field unique values to whats in the map extent. There are thousands of unique values which doesn't take long to populate the combobox but to help the end user I would like to limit those to what's in the map extent.

Here's my python code so far.  You select the specific layer, then it sorts and pushes the unique values to a combobox. Once you select a feature from the drop down, it selects and zooms to that feature.

import arcpy
import pythonaddins


class leveeLayerListSelector(object):
    """Implementation for LeveeSearch_addin.comboboxLayerList (ComboBox)"""
    def __init__(self):
        self.items = []
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWW'
        self.width = 'WWWWWW'    
    def onEditChange(self, text):
        pass
    def onFocus(self, focused):
        if focused:  
            self.mxd = arcpy.mapping.MapDocument('current')  
            layers = arcpy.mapping.ListLayers(self.mxd)  
            self.items = []  
            for layer in layers:  
                self.items.append(layer.name) 
    def onEnter(self):
        pass
    def refresh(self):
        pass
    def onSelChange(self, selection):
        global fc  
        fc = arcpy.mapping.ListLayers(self.mxd, selection)[0]


    
class leveeSystemSelector(object):
    """Implementation for LeveeSearch_addin.comboboxLeveeSystem (ComboBox)"""
    def __init__(self):
        self.items = []
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW'
        self.width = 'WWWWWW'
    def onSelChange(self, selection):
        self.mxd = arcpy.mapping.MapDocument('current')
        df = arcpy.mapping.ListDataFrames(self.mxd, "Layers") [0]
        arcpy.SelectLayerByAttribute_management(layer, "NEW_SELECTION", "System_Name = '" + selection + "'")
        df.zoomToSelectedFeatures()
        arcpy.RefreshActiveView()  
    def onEditChange(self, text):
        pass
    def onFocus(self, focused):        
        self.mxd = arcpy.mapping.MapDocument('current')
        global layer  
        layer = arcpy.mapping.ListLayers(self.mxd, fc)[0]  
        self.items = []  
        values = [row[0] for row in arcpy.da.SearchCursor(layer, ["System_Name"])]  
        for uniqueVal in sorted(set(values)):  
            self.items.append(uniqueVal)  
    def onEnter(self):
        pass
    def refresh(self):
        pass

-Steven

0 Kudos
1 Solution

Accepted Solutions
WesMiller
Regular Contributor III

Did you see this post Dynamically Select Feature in Map with Python Addin

EDIT:

Looks like you'll need to add something similar to below

mxd = arcpy.mapping.MapDocument('current')
df = arcpy.mapping.ListDataFrames(mxd)[0]
extent = df.extent
extentPoly = arcpy.Polygon(arcpy.Array([arcpy.Point(extent.XMin, extent.YMin), arcpy.Point(extent.XMin, extent.YMax), arcpy.Point(extent.XMax, extent.YMax), arcpy.Point(extent.XMax, extent.YMin)]))
arcpy.SelectLayerByLocation_management(yourlayer, 'intersect', extentPoly )

View solution in original post

12 Replies
WesMiller
Regular Contributor III

Did you see this post Dynamically Select Feature in Map with Python Addin

EDIT:

Looks like you'll need to add something similar to below

mxd = arcpy.mapping.MapDocument('current')
df = arcpy.mapping.ListDataFrames(mxd)[0]
extent = df.extent
extentPoly = arcpy.Polygon(arcpy.Array([arcpy.Point(extent.XMin, extent.YMin), arcpy.Point(extent.XMin, extent.YMax), arcpy.Point(extent.XMax, extent.YMax), arcpy.Point(extent.XMax, extent.YMin)]))
arcpy.SelectLayerByLocation_management(yourlayer, 'intersect', extentPoly )
StevenGraf1
Occasional Contributor III

So basically I need to do the following:

-Select my layer based on location (which would be the extent of the map)

-Push those field values from the selected into the combobox

-Then select by attributes

-Steven

0 Kudos
WesMiller
Regular Contributor III

Sounds right to me. let me know how it turns out. I tested the code in my armap python interpreter and it selects only the features that intersect with data frames extent. You may want to change the data frame [0] to the active data frame.

0 Kudos
StevenGraf1
Occasional Contributor III

That selects all the features, but it doesn't push the field unique values to the combobox.

Wonder if I need to create a temporary layer from the select by location results to populate the combobox with the unique values.

-Steven

0 Kudos
StevenGraf1
Occasional Contributor III

Nevermind, It does populate the unique values in the combobox for the select by location query.  It seems to only run once though.  Going to test some more.

-Steven

0 Kudos
WesMiller
Regular Contributor III

try using

arcpy.env.overwriteOutput = "true"

0 Kudos
StevenGraf1
Occasional Contributor III

Guess I should clarify a bit more. The Location search fires every time, but the unique field values only get pushed to the combobox the first time.  I have a button set to clear selection.

Here's my script.  It's a bit different from my original.

import arcpy
import pythonaddins


class LeveeSystemName(object):
    """Implementation for LeveeSearch_addin.LeveeSystemName (ComboBox)"""
    def __init__(self):
        self.items = []
        self.editable = True
        self.enabled = True
        self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW'
        self.width = 'WWWWWW'    
    def onEditChange(self, text):
        pass
    def onFocus(self, focused):
        global layer
        global df
        self.mxd = arcpy.mapping.MapDocument('current')
        layer = arcpy.mapping.ListLayers(self.mxd, "Levee Centerline (Segment Only)")[0]        
        df = arcpy.mapping.ListDataFrames(self.mxd, "Region VII") [0]
        extent = df.extent  
        extentPoly = arcpy.Polygon(arcpy.Array([arcpy.Point(extent.XMin, extent.YMin), arcpy.Point(extent.XMin, extent.YMax), arcpy.Point(extent.XMax, extent.YMax), arcpy.Point(extent.XMax, extent.YMin)]))  
        arcpy.SelectLayerByLocation_management(layer, 'intersect', extentPoly )          
        self.items = []  
        values = [row[0] for row in arcpy.da.SearchCursor(layer, ["FC_SYSTEM.System_Name"])]  
        for uniqueVal in sorted(set(values)):  
            self.items.append(uniqueVal)
        arcpy.RefreshActiveView()
    def onSelChange(self, selection):
        self.mxd = arcpy.mapping.MapDocument('current')
        arcpy.SelectLayerByAttribute_management(layer, "NEW_SELECTION", "FC_SYSTEM.System_Name = '" + selection + "'")
        df.zoomToSelectedFeatures()
        arcpy.RefreshActiveView()
    def onEnter(self):
        pass
    def refresh(self):
        pass


class ClearSelected(object):
    """Implementation for LeveeSearch_addin.ClearSelected (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        arcpy.SelectLayerByAttribute_management(layer, "CLEAR_SELECTION")

-Steven

WesMiller
Regular Contributor III

Do you have it working now?

Are you planning on repopulating with your clear selected button?

StevenGraf1
Occasional Contributor III

I was wanting it to repopulate the combo box after clearing the selection but it's not.  After the entire script runs, the only piece that runs is the selection by location.  The combobox never repopulates so I can select a new value and zoom to.

-Steven

0 Kudos