Select to view content in your preferred language

ArcPy and Tkinter

11866
14
Jump to solution
05-22-2012 07:09 AM
OlivierVoyer
Occasional Contributor
Hi,

I would like to know if ArcPy currently supports executing scripts using Tkinter inside ArcMap, i.e directly from the Python Window or in the ArcToolbox (embedded)?

When I tried to display a simple "Hello World" form, ArcMap 10 crashed on me.

Regards,

Olivier
1 Solution

Accepted Solutions
NobbirAhmed
Esri Regular Contributor
If you want to run your algorithm from command line and want the user to interact in the middle of the algorithm then a Python GUI program is your only option. As Esri does not officially support any such GUI yet - this forum is the only option to get help 😞

On the other hand, if the user will interact with your script through some GUI then script tool framework is a good option. The Tool Validator class mechanism will allow you to fill up options dynamically based on what selection is made in other parameters.

In case you want to explore the script tool mechanism, you can start here:
http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/A_quick_tour_of_creating_script_tools/...

This topic elaborates how to dynamically update parameter choices: http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/Customizing_script_tool_behavior/00150...

View solution in original post

14 Replies
MathewCoyle
Honored Contributor
You can see this example to get started on integrating ArcMap and Tkinter in scripting tools.
http://resources.arcgis.com/gallery/file/Geoprocessing-Model-and-Script-Tool-Gallery/details?entryID...
0 Kudos
NobbirAhmed
Esri Regular Contributor
@Mathew,
The TkInter example in your link works outside of ArcMap - as a standalone GUI interface.

@Olivier
TkInter does not work from within ArcMap - it crashes Arcmap. The reason is TkInter's event loop does not work with ArcMap. By the way, what are trying to achieve through the GUI?
0 Kudos
MathewCoyle
Honored Contributor
The example I posted works in ArcMap as a script tool. I just used it yesterday.
0 Kudos
NobbirAhmed
Esri Regular Contributor
Wow! Great - it works. Until now all my attempts to get TkInter work in ArcMap ended in crash. Thanks a lot.

Do you have any other example that you can share?
0 Kudos
MathewCoyle
Honored Contributor
No unfortunately, my independent forays into integrating tkinter and script tools also failed, so I rummaged around and found that example which works by integrating the widget into a frame tied to the script tool itself, or so it seems. Whoever wrote it is far more knowledgeable in tkinter than I.

When I tried implementing tkinter myself first I would use the standard script function implementation, which doesn't seem to work.
class MyApp(object):
    def __init__(self, root):
        self.root = root
        [...]
def main():
    root = Tk()
    myapp = MyApp(root)
    root.title("Export Tool")
    root.update()
    root.mainloop()
if __name__ == '__main__':
    main()

Implementing the widget in this manner seems to be the silver bullet, tying the widget to the application under the __init__ and then calling your widget creation and geoprocessing under those new sub-functions seems to be the way to go.
class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.createWidgets(master)

    def createWidgets(self, master):
        [...]
root = Tk()
app = Application(master=root)
app.master.title(Title)
app.mainloop()
0 Kudos
NobbirAhmed
Esri Regular Contributor
WARNING: I saved and closed the map document that worked with Mathew's sample. Now, whenever I attempt to re-open that particular map document, it crashes 😞

@Mathew: Thanks for following up.

@Olivier: officially, ArcPy does not support Tkinter inside ArcMap.

Olivier, I am interested about your need for using Tkinter in ArcMap. Could you please let me know what you are trying to do with a custom GUI? I would like to investigate why your workflow cannot be implemented with our current scripting framework. Thanks.
0 Kudos
MathewCoyle
Honored Contributor
WARNING: I saved and closed the map document that worked with Mathew's sample. Now, whenever I attempt to re-open that particular map document, it crashes 😞


That is fairly odd. I haven't seen that behaviour in my tests. Did you try running an MXD doctor on it? Was it a fairly complicated MXD before you tried to tool or a new one? Have you tried creating a new MXD with just one simple layer with a few features, save that, run the tool, save and close the MXD then see if you can reopen it?

I made a few modifications to the script, mainly to accept tool parameters and any data type.

# Author:   Jennifer (esri_id: jenn775)
# Created:  July 20, 2010
# Edits:    Mathew Coyle, May 24, 2012

from Tkinter import *
import arcpy

# SelectPopup.py sample Python script using Tkinter for a user interface
# User selects feature from list, code selects and zooms to feature

# Use in ArcMap by attaching script to a button for best results
# In ArcGIS 10, you can add scripts and models to buttons in the UI without using VBA.
# Create a Python script tool using this script and then
# see "Adding a custom tool to a menu or toolbar" in this help topic:
# http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//002400000005000000.htm

Layer = arcpy.GetParameterAsText(0) # Layer
SelField =  arcpy.GetParameterAsText(1) # Field to Select
Title =  arcpy.GetParameterAsText(2) # Title (optional)

# Troubleshooting messages
#arcpy.AddMessage("Layer is "+repr(Layer))
#arcpy.AddMessage("Selection field is "+repr(SelField))
#arcpy.AddMessage("Title is " + repr(Title))

class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.createWidgets(master)

    def createWidgets(self, master):
        self.yScroll  =  Scrollbar ( self, orient=VERTICAL )
        self.yScroll.grid ( row=0, column=1, sticky=N+S )
        self.stList = Listbox (self, yscrollcommand=self.yScroll.set)
        self.stList.grid( row=0, column=0 )
        self.yScroll["command"] = self.stList.yview
        # populate list with choices, sorted ascending
        mxd = arcpy.mapping.MapDocument("CURRENT")
        for lyr in arcpy.mapping.ListLayers(mxd):
            if lyr.name == Layer:
                break
        # for large datasets where the selection field contains many blanks or
        # non-unique values, you can create a summary table and set SelTable
        # equal to it for faster creation of the selection dialog
        SelTable = lyr.dataSource
        rows = arcpy.SearchCursor(SelTable, "", "", SelField, SelField + " A")
        oldVal = ""
        for row in rows:
            newVal = row.getValue(SelField)
            #only add value to Listbox if it is not a duplicate
            if newVal <> oldVal:
                self.stList.insert( END, row.getValue(SelField) )
            oldVal = newVal
        #add selection and quit button
        self.selButton = Button (self, text='Select', command=self.selectFeat)
        self.selButton.grid( row=0, column=2 )
        self.quitButton = Button ( self, text='Quit', command=master.destroy )
        self.quitButton.grid( row=1, column=2 )

    def selectFeat(self):
        sel = self.stList.curselection()
        myFeature = self.stList.get(sel[0])

        def BuildQuery(table, field, operator, value=None):
            """Generate a valid ArcGIS query expression

            arguments

              table - input feature class or table view
              field - field name (string)
              operator - SQL operators ("=","<>", etc)
                 "IS NULL" and "IS NOT NULL" are supported
              value - query value (optional)

            """
            # Adds field delimiters
            qfield=arcpy.AddFieldDelimiters(table,field)

            # tweak value delimeter for different data types
            if type(value) == str:
                # add single quotes around string values
                qvalue = "'" + value + "'"
            elif value == None:
                # drop value when not specified (used for IS NULL, etc)
                qvalue = ""
            else:
                # numeric values are fine unmodified
                qvalue = value

            sql = "{0} {1} {2}".format(qfield,operator,qvalue)
            #print repr(sql)
            return sql.strip()

        where = BuildQuery(Layer, SelField, "=", myFeature)
        arcpy.AddMessage(where)
        arcpy.SelectLayerByAttribute_management(Layer, "NEW_SELECTION", where)
        mxd = arcpy.mapping.MapDocument("CURRENT")
        for df in arcpy.mapping.ListDataFrames(mxd):
            if df.name == mxd.activeView:
                df.zoomToSelectedFeatures()
                arcpy.RefreshActiveView()


root = Tk()
app = Application(master=root)
app.master.title(Title)
app.mainloop()
0 Kudos
OlivierVoyer
Occasional Contributor
Thank you very much for your answers! Is is much appreciated 🙂

@Matthew: I will git it a try! Thank you.

@Olivier: officially, ArcPy does not support Tkinter inside ArcMap.

Olivier, I am interested about your need for using Tkinter in ArcMap. Could you please let me know what you are trying to do with a custom GUI? I would like to investigate why your workflow cannot be implemented with our current scripting framework. Thanks.


Cool, thank you. I suspected tkinter would not work inside ArcMap, but I just wanted to confirm... now I know!

What I would like to achieve is create a simple form allowing the user to set some parameters using dropdown controls, textbox, checbox, etc. along with buttons. This form would then run my ArcPy script after user clicked "Run". Is there any alternative to tkinter to achieve that inside ArcMap?
0 Kudos
NobbirAhmed
Esri Regular Contributor
What I would like to achieve is create a simple form allowing the user to set some parameters using dropdown controls, textbox, checbox, etc. along with buttons. This form would then run my ArcPy script after user clicked "Run".


Geoprocessing script tool framework is an excellent mechanism to do so. If you let me know what type of values (data) you want for your GUI controls (dropdown, textbox, checkbox & buttons) I can provide you links to help topics to get it done. Alternatively, you can email me at nahmed@esri.com - we'll post the summary once something is figured out.

@Mathews: thanks a lot for the update. I'll give another try.
0 Kudos