I would like to be able to create a Python toolbox tool (or a Python script tool) where a choice made from the first parameter (Category in the images below) changes the Display Name of other parameters (which initialize as Sub Category 1 and Sub Category 2 in the images below).
These images are mockups.
After opening the tool I choose Category B for Category.
I would like that choice to change the Display Names of:
- Sub Category 1 to Sub Category B1 (choosing Category A would set Sub Category A1)
- Sub Category 2 to Sub Category B2 (choosing Category A would set Sub Category A2)
Something like below (where I have mocked up the Display Name changes) but with the first parameter green rather than red.
I tried tool validation of a Python script tool first, but seemed to be blocked by the read-only Display Name there. I then moved to a Python Toolbox tool instead because that adds some extra functionality and I was hoping might remove the read-only Display Name limitation.
My attempt to code this as a Python Toolbox tool is below, but it seems not to be working because displayName is read-only there too.
Is there any ArcPy way to meet the requirement that I describe above?
import arcpy
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Toolbox"
self.alias = ""
# List of tool classes associated with this toolbox
self.tools = [Tool]
class Tool(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "Tool"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
# First parameter
param0 = arcpy.Parameter(
displayName="Category",
name="category",
datatype="String",
parameterType="Required",
direction="Input")
param0.filter.list = ['Category A', 'Category B']
# Second parameter
param1 = arcpy.Parameter(
displayName="Sub Category 1",
name="subcategory_1",
datatype="String",
parameterType="Required",
direction="Input")
# Third parameter
param2 = arcpy.Parameter(
displayName="Sub Category 2",
name="subcategory_2",
datatype="String",
parameterType="Required",
direction="Input")
params = [param0,param1,param2]
return params
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."""
if parameters[0].value == "Category A":
parameters[1].displayName = "Sub Category A1"
parameters[2].displayName = "Sub Category A2"
elif parameters[0].value == "Category B":
parameters[1].displayName = "Sub Category B1"
parameters[2].displayName = "Sub Category B2"
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 execute(self, parameters, messages):
"""The source code of the tool."""
return
I am using ArcGIS 10.2.2 for Desktop.
Answer
You know, anything is probably possible but that doesn't mean it is worth the effort. UpdateParameters is meant to update parameter values dynamically. Not parameter display names.
If I were trying to do this, I would create a Python Toolbox with two tools in it, ToolA for Category A and ToolB for Category B, each tool having the appropriate DisplayNames for its parameters.
To make the tool selection pretty simple for a user, I would then create a Python Add-in with two buttons (Category A and Category B). Then save the Python Toolbox into the Install Folder of your Python Add-in. When the user clicks the Category A button, launch ToolA from the Python Toolbox, when they click the Category B button on the Python Add-In, launch the ToolB from the Python Toolbox.
You can accomplish this using the pythonaddins.GPToolDialog function like so:
import os
import arcpy
import pythonaddins
relPath = os.path.dirname(__file__)
class CAT_A(object):
"""Implementation for Project_addin.CategoryA (Button)"""
def __init__(self):
self.enabled = True
self.checked = False
def onClick(self):
PythonTBX = relPath + r"\YourToolBox.pyt"
pythonaddins.GPToolDialog(PythonTBX, "ToolA")
class CAT_B(object):
"""Implementation for Project_addin.CategoryB (Button)"""
def __init__(self):
self.enabled = True
self.checked = False
def onClick(self):
PythonTBX = relPath + r"\YourToolBox.pyt"
pythonaddins.GPToolDialog(PythonTBX, "ToolB")
There's a couple of advantages to this approach.
- Stupid simple deployment of the Toolbox through a Python Add-in
- A user can then access the tools through a simple button on a toolbar rather than through a series of nested menus in a toolbox in their Catalog Window and doesn't have to create a Catalog Connection to the location where the toolbox is hosted on their system.
- An end user who wanted to alter the source code of the toolbox or tools is going to need to step up their game a little bit as they'll need to figure out that to get to the source code of the toolbox, they have to find the assembly cache where the addin is loaded. It's not obvious where this is located and the end user will not see this toolbox in their my toolboxes in catalog. The only way to access it will be through the Add-in unless they create a Catalog Connection to the assembly cache.
- You can restrict the Addin Manager to only install Trusted (Signed) Addins, then Sign the addin with your signing certificate. If anyone does manage to locate and modify the source code, the signature will become invalid and the Addin will uninstall automagically.
No comments:
Post a Comment