|
POST
|
Comboboxes are kind of finnicky. Try baby stepping it... Replace any code contained in any of the combobox methods with a pass statement:
class MyComboBox(object):
"""Implementation for MyComboBox"""
def __init__(self):
self.editable = True
self.enabled = True
self.dropdownWidth = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.width = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
def onSelChange(self, selection):
"""Occurs when the user makes a selection from the ComboBox drop-down menu"""
pass
def onEditChange(self, text):
"""Occurs when the user manually enters text into the ComboBox"""
pass
def onFocus(self, focused):
"""Occurs when the user clicks on the Combobox, giving the ComboBox focus"""
pass
def onEnter(self):
"""Occurs when the user presses the 'Enter' key while the ComboBox has focus"""
pass
def refresh(self):
"""Occurs after a value is established within the ComboBox"""
self.refresh()
Next, let's just make sure we can get the combobox to dynamically populate with a list of layers in the TOC when given focus
def onFocus(self, focused):
"""Occurs when the user clicks on the Combobox, giving the ComboBox focus"""
# Empty the Combobox items list
self.items = []
# Establish a reference to the current MXD
mxd = arcpy.mapping.MapDocument("Current")
# Establish a reference to the first DataFrame object in the current MXD
df = arcpy.mapping.ListDataFrames(mxd)[0]
# Build a List of LayerObjects contained in the first DataFrame of the current MXD
Layers = arcpy.mapping.ListLayers(mxd, "*", df)
# Iterate through the Layers
for Layer in LayerList:
# Append the current Layer's name to the Items List
self.items.append(Layer.name)
Once onFocus() has been invoked and you have a list of layers populating dynamically in the Combobox, we can begin thinking about what we want to do with the Selection in the Combobox. That's where the onSelection() and onEnter() events come into play. onEditChange() is really just another method of making a selection by allowing the user to type values directly into the box. Valuable when your item list is really long, so that the user doesn't have to scroll through values. For this though, we'll just focus on the onSelection() method. So now that we can make selections in the Combobox, what do we want to do with them? Let's look at onSelection()
def onSelChange(self, selection):
# Because 'mxd' and 'df' weren't given global scope, we have to reestablish them
# in order to use them in this method
mxd = arcpy.mapping.MapDocument("Current")
df = arcpy.mapping.ListDaaFrames(mxd)[0]
# Reference the first Layer in the DataFrame of the MXD which has a name that matches
# the current selection
layer = arcpy.mapping.ListLayers(self.mxd, selection, df)[0]
desc = arcpy.Describe(layer.dataSource)
extent = desc.Extent
fishnet = arcpy.CreateFishnet_management(r'in_memory\fishnet',
'%f %f' %(extent.XMin, extent.YMin),
'%f %f' %(extent.XMin, extent.YMax),
0, 0, 10, 10,
'%f %f' %(extent.XMax, extent.YMax),
'NO_LABELS',
'%f %f %f %f' %(extent.XMin, extent.YMin, extent.XMax, extent.YMax), 'POLYGON')
arcpy.RefreshActiveView()
I would encourage you to implement each of these in baby steps, rebuilding and testing the addin after each change so that if you do find problems, you know where to look. Print statements can also come in very handy for this purpose.
... View more
06-10-2014
08:52 AM
|
0
|
0
|
2308
|
|
POST
|
Anyone know how to Flash a Selected Feature using Python or to call the ArcObjects function through Python? I have a process set up to allow the user to easily Query a Layer and then Zoom to the Selected Feature, immediately after zooming to the feature though, I want the feature to Flash the same as it would through the Identify Window in order to draw the user's attention to it. I tried creating a crude version of it using SelectLayerByAttribute, but it's god-awful slow.
def crudeFlash(FeatureLayer, Query):
mxd = arcpy.mapping.MapDocument("Current")
df = arcpy.mapping.ListDataFrames(mxd)[0]
arcpy.SelectLayerByAttribute_management(FeatureLayer, "NEW_SELECTION", Query)
df.zoomToSelectedFeatures()
arcpy.SelectLayerByAttribute_management(FeatureLayer, "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management(FeatureLayer, "NEW_SELECTION", Query)
arcpy.SelectLayerByAttribute_management(FeatureLayer, "CLEAR_SELECTION")
>>> crudeFlash("MyLayer", '"NAME" = ' + "'MyFeature'")
The reason I don't want to just leave the feature selected is that I don't want to create a situation where the User might then run some sort of GeoProcess and it only executes against the single selected feature.
... View more
06-09-2014
12:50 PM
|
1
|
3
|
2542
|
|
POST
|
With ESRI going all in on Python, and Apple comparing Swift to Python several times at WWDC, I imagine ESRI will probably come to support it. I wouldn't expect to see it at the 2015 DevSummit, but hopefully 2016. The good thing is that since it is interoperable with Obj-C APIs, you should be able to mix-and match as needed until ESRI can release a full blown Swift SDK.
... View more
06-04-2014
08:06 AM
|
0
|
0
|
1559
|
|
POST
|
The general workflow is like you have it above. Make your field info object base on your existing feature layer, then you want to make a new feature layer using the optional "field_info" attribute. Thanks Matt & Wayne, I got it going now. Good to know that an export is required. Geeze ESRI, I don't even have words for this nonsense. This is so not neccesary...
... View more
04-24-2014
12:29 PM
|
0
|
0
|
4950
|
|
POST
|
Hey Josh, That's true, I didn't notice that. Interesting thing is that the intellisense in the python window suggests setvisible, not setVisible. I changed it anyway, but still no dice. It doesn't throw an exception in either case which is also strange. It would be really cool if it worked. lol. Would be nice to be able to turn fields off prior to an export in order to omit them from the result.
... View more
04-24-2014
10:03 AM
|
0
|
0
|
4950
|
|
POST
|
Anyone know how to make fields in a Feature Layer visible or hidden? Tried using the Field Info object, no luck there... desc = arcpy.Describe("FeatureLayer") field_info = desc.fieldInfo visibleFields = ["ID", "NAME", "Rank", "Count"] for index in xrange(0, field_info.count): fieldName = str(field_info.getfieldname(index)) if fieldName in visibleFields: print "Found Field " + str(fieldName) + " in visibleFields. Setting Visible..." field_info.setvisible(index, "VISIBLE") else: print "Field " + str(fieldName) + " not found in visibleFields. Setting Hidden..." field_info.setvisible(index, "HIDDEN") Tried tossing a RefreshActiveView() onto the end, that didn't help either.
... View more
04-24-2014
09:18 AM
|
0
|
6
|
6484
|
|
POST
|
You need to reference it using self. ToolClass is the name of your class and self is how the class is referenced when you are within that class. Result = self.MyFunction(inFeatureLayer) I don't think there is anything in the .pyt format that would prevent this functionality but I have not tested this myself. I reached out to Chris Fox earlier this morning and that was the exact answer he gave me. Makes total sense, thanks for posting. I knew it was something simple!
... View more
04-23-2014
10:10 AM
|
0
|
0
|
1685
|
|
POST
|
So after I made the changes:
class Toolbox(object):
def __init__(self):
"""Toolbox Initialization Settings"""
self.label = "My Very Own Toolbox"
self.alias = MVO_tbx"
# List of the tools contained within the Toolbox
self.tools = [ToolClass]
class ToolClass(object):
def __init__(self):
"""Define the tool."""
self.label = "MyTool"
self.description = "No Description"
self.canRunInBackground = True
def getParameterInfo(self):
"""Establish the Parameters"""
# Input Features Parameter
param0 = arcpy.Parameter(
displayName="Features",
name="in_Features",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
param0.filter.list = ["Point"]
def isLicensed(self):
"""Set whether tool is licensed to execute."""
return True
def updateParameters(self, parameters):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
return
def updateMessages(self, parameters):
"""Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation."""
return
def MyFunction(self, inFeatureLayer):
arcpy.SelectLayerByAttribute_management(inFeatureLayer, "NEW_SELECTION", '"ID" = ' + "'123456'")
SiteList = list(r[0] for r in arcpy.da.SearchCursor(inFeatureLayer, "ID"))
return SiteList
def execute(self, parameters, messages):
"""The source code of the tool"""
inFeatureLayer = arcpy.parameters[0].valueAsText
Result = MyFunction(inFeatureLayer) # Why doesn�??t this work???
# Do something with the result
When it gets to the method call in execute, I receive the error:
TypeError: unbound method �??MyFunction�?� must be called with �??ToolClass�?� instance as first argument (got Layer instead)
I've tried calling the method by referencing it via Class.method:
def execute(self, parameters, messages):
"""The source code of the tool"""
inFeatureLayer = arcpy.parameters[0].valueAsText
Result = ToolClass.MyFunction(inFeatureLayer) # Why doesn�??t this work???
# Do something with the result
Posts on StackOverflow seem to indicate that I need to instantiate the Class Objectand then call the Tool from the instance. I'm not really sure how to do that.
... View more
04-23-2014
05:58 AM
|
0
|
0
|
1685
|
|
POST
|
Yes that should allow you to reference it within the class using self. Sweet. Thanks Mat!
... View more
04-22-2014
09:42 AM
|
0
|
0
|
1685
|
|
POST
|
How do i submit that you answered what i had asked to give you credit for it? Hit the check mark on the right side of his post that answered your question.
... View more
04-22-2014
09:38 AM
|
0
|
0
|
4001
|
|
POST
|
You are trying to reference it at the class level without using self which won't work. You need to pass self to the function so the class can reference it, declare it within another function, or reference it outside the class. So do I just need to add self as the first parameter to the function like so?
MyFunction(self, param1, param2, param3):
# Do stuff
... View more
04-22-2014
09:25 AM
|
0
|
0
|
1685
|
|
POST
|
I'm pretty sure this is possible and I'm just missing something relatively basic. I wrote a little function to do something (proprietary) and I want to leverage it within the execute function of a Python Toolbox. For the sake of keeping the code tidy, I'd like to define it within the Tool Class rather than within the Execute Function of the Tool Class. like so: def updateMessages(self, parameters): """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation.""" return def MyFunction(inFeatureLayer): arcpy.SelectLayerByAttribute_management(inFeatureLayer, "NEW_SELECTION", '"ID" = ' + "'123456'") SiteList = list(r[0] for r in arcpy.da.SearchCursor(inFeatureLayer, "ID")) return SiteList def execute(self, parameters, messages): """The source code of the tool""" inFeatureLayer = arcpy.parameters[0].valueAsText Result = MyFunction(inFeatureLayer) # Why doesn???t this work??? # Do something with the result When I do that however, the Execute function doesn't see it. The only way I can get the execute function to see my function is by defining it within the execute function, like so: def updateMessages(self, parameters): """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation.""" return def execute(self, parameters, messages): """The source code of the tool""" def MyFunction(inFeatureLayer): arcpy.SelectLayerByAttribute_management(inFeatureLayer, "NEW_SELECTION", '"ID" = ' + "'123456'") SiteList = list(r[0] for r in arcpy.da.SearchCursor(inFeatureLayer, "ID") return SiteList inFeatureLayer = arcpy.parameters[0].valueAsText Result = MyFunction(inFeatureLayer) # This works, but it seems more elegant to me if I could define it outside of Execute # Do something with the result This seems like it should be wholly possible. What I am doing wrong?
... View more
04-22-2014
08:56 AM
|
0
|
8
|
1785
|
|
POST
|
Hi guys, All good suggestions. I should have made it clear in my prior post that I know how to do this from a standard geoprocessing standpoint. I'm trying to figure out a way to do in a much much faster way. In my smallest market, there are over 400 retailers that have to be analyzed. In order to get the retailer with the largest number of features within it's search radius, I have to analyze each feature in the dataset on its own. From there, once I know which retailer has the most retailers within its search radius, I have to copy all of those selected retailers to a new dataset, pretty simple, delete them from the original dataset, also simple, then iterate the process all over again to determine which retailer remaining in the dataset returns the next highest amount of retailers in its search radius. Then keep iterating until there are no more retailers left in the original dataset. Here's what I'm doing currently just to try and get the first retailer with the most retailers in its search radius.
>>> inFeatureLayer = "Retailers"
... ScoreField = "PTS"
... SearchRadius = ".5 Miles"
... # Determine what the highest set of values is in the FeatureLayer
... maxValue = arcpy.SearchCursor(inFeatureLayer, "", "", "", ScoreField + " D").next().getValue(ScoreField)
... # Select the records which have the max value in the dataset
... arcpy.SelectLayerByAttribute_management(inFeatureLayer, "NEW_SELECTION", '"' + ScoreField + '" = ' + str(maxValue))
... # Get a list of the StoreIDs of the currently selected records
... StoreList = list(r[0] for r in arcpy.da.SearchCursor(inFeatureLayer, "STOREID"))
... # Establish a variable to hold the StoreID of the record with the most features intersecting its radius
... MaxRecord = ""
... HighestSelected = 0
... # Iterate through the StoreList
... for Store in StoreList:
... print "Evaluating Store " + str(Store) + "..."
... # Create a new selection, selecting the current store in the iteration
... arcpy.SelectLayerByAttribute_management(inFeatureLayer, "NEW_SELECTION", '"STOREID" = ' + "'" + str(Store) + "'")
... # Select the Stores within search radius of the current Store
... arcpy.SelectLayerByLocation_management(inFeatureLayer, "WITHIN_A_DISTANCE", inFeatureLayer, SearchRadius, "NEW_SELECTION")
... # Create a Describe Object of the Stores Layer
... desc = arcpy.Describe(inFeatureLayer)
... # Get the Number of Selected Records
... SelectCount = len(desc.FIDSet)
... # If the SelectCount is greater than the current HighestSelected Count
... if SelectCount > HighestSelected:
... print "Returned " + str(SelectCount) + " stores within " + SearchRadius + " of Store " + str(Store) + " which is greater than the current Selection Count of " + str(HighestSelected) + " for Store " + str(MaxRecord)
... HighestSelected = SelectCount
... MaxRecord = Store
... # Otherwise
... else:
... print "Returned " + str(SelectCount) + " stores within " + SearchRadius + " of Store " + str(Store) + " which is less than the current Selection Count of " + str(HighestSelected) + " for Store " + str(MaxRecord)
... # Do Nothing and Continue
... pass
... print "StoreID: " + str(MaxRecord) + " was the record with the most features within " + SearchRadius + " with a total count of " + str(HighestSelected) + "."
It takes a really long time though because it has to analyze each feature seperately. I'm looking for a way to make this move much quicker.
... View more
04-15-2014
05:38 AM
|
0
|
0
|
1131
|
|
POST
|
I need to figure out how to determine which feature in a dataset has the most features within a defined radius. I'm thinking I need to loop through the entire dataset, perform a Select Layer by Locaiton function, load the result ID and number of features into a list, and continue iterating only updating the list if another feature comes along with a higher number of features. I'm open to ideas on how to best accomplish this.
... View more
04-14-2014
12:04 PM
|
0
|
5
|
1337
|
|
POST
|
Does anyone know of a good way to sort records by attribute value without the sort_management function? I need do the following: Iterate through an FC, get the feature with the highest point value Select all of the features within 5 miles of the selected feature, Copy all of those selected features to a new FC Delete the selected from the original FC Continue iterating until the original FC has no features remaining. I can manage everything except getting the feature with the highest attribute value in the FC. I only have a Basic license so I can't use sort management. Any ideas?
... View more
04-10-2014
12:00 PM
|
0
|
2
|
1490
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 06-11-2015 12:02 PM | |
| 2 | 02-04-2016 02:35 PM | |
| 1 | 04-11-2017 12:51 PM | |
| 1 | 08-07-2015 11:00 AM | |
| 4 | 06-19-2015 01:44 PM |
| Online Status |
Offline
|
| Date Last Visited |
11-11-2020
02:23 AM
|