Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I need to build a custom toolbar that can launch the following items:

  • A Python script tool - shouldn't be a problem, as you can already attach these to a toolbar
  • Out of the box functions such as the Editor Toolbar maybe or a standard GP tool - again, should be do-able as you can already attach these to a toolbar
  • A Python script that launches a PyQT/wxPython/Tk GUI. This is the tricky one I think. Now, this GUI does not need to interact with ArcMap. My other custom tools will do all of that, this GUI is for the user to setup parameters that will get written to a XML config file. It will also do some arcpy calls in the background and slurp some data and values out of a geodatabase and push them to the same XML config file.

enter image description here

So the question is - how to do this as simply as possible? It appears I cannot attach a Python script (that is not encased in a tool) to a toolbar in ArcMap. I'm thinking I'm going to have to go the Add-In route and create a simple Toolbar with buttons to kick off each of the items listed above. VBA is not an option. Thoughts?

share|improve this question
    
In the What's New in ArcGIS 10.1 available via a link from resources.esri.com it says: "At ArcGIS 10.1, you can program your own buttons and tools using Python add-ins. Python toolboxes are a new kind of toolbox you can create with Python." These sound like they will help you when that version is released. –  PolyGeo Mar 14 '12 at 11:45
    
@PolyGeo - Yeah, I know about that, but my client will be on 10.0 for a long time, so waiting around for 10.1 isn't an option either. –  Chad Cooper Mar 14 '12 at 14:18
add comment

1 Answer 1

up vote 4 down vote accepted

@ChadCooper, perhaps I'm overlooking something, but with regard to your 3rd case:

A Python script that launches a PyQT/wxPython/Tk GUI..

Is there a reason why you couldn't use the .Net Process API (see System.Diagnostics) to execute your custom Python script over Standard In/Out? Of course, this sort of architecture will assume a proper version of Python is installed and equipped with any additional libs you require. I think you'd just want to extend an ICommand object and use the Process API in its Click() event. This example (which was an experiment only) called a .py script that used dbfpy to read the columns in a DBF file and return them as a list to a .Net application.

private static List<string> _readDbfOutput;

public static List<string> ReadDbfTable(string dbfPath, int limit)
{
    // start a fresh output object..
    _readDbfOutput = new List<string>();
    _readDbfOutput.Clear();

    // ready..
    string executable = "C:\Python27\python.exe";
    string fullUtilPath = "C:\some_app\utils\read_dbf_table.py";

    // The path to the python file and it's arguments become a single input
    // submitted to the python runtime. In this case, I've got somethign like:
    // C:\>C:/Python27/python.exe C:\some_app\utils\read_dbf_table.py -f C:/data/some_shapefiles.dbf -l 100

    // dbfPath and limit were method arguments..
    string exeArguments = fullUtilPath + " -f " + dbfPath + " -l " + limit.ToString();

    ProcessStartInfo startInfo = new ProcessStartInfo(executable, exeArguments);
    startInfo.UseShellExecute = false;
    startInfo.CreateNoWindow = true;
    startInfo.RedirectStandardOutput = true;  // necessary if you need to listen..
    startInfo.RedirectStandardInput = false;  // necessary if you send more inputs..
    startInfo.StandardOutputEncoding = System.Text.Encoding.ASCII;

    Process proc = new Process();

    // ReadingDbfTable is my redirected standard input..
    proc.OutputDataReceived += new DataReceivedEventHandler(ReadingDbfTable);
    proc.StartInfo = startInfo;
    proc.Start();
    proc.BeginOutputReadLine();

    // WaitForExit() may need to be wrapped in a Try or Using block.
    // Will it run indefinitely if the script fails?
    proc.WaitForExit();
    proc.Close();

    return _readDbfOutput;
}

/// Handle redirected STDOUT.
private static void ReadingDbfTable(object sendingProc, DataReceivedEventArgs stdOutput)
{
    if ( ! String.IsNullOrEmpty(stdOutput.Data) )
    {
        _readDbfOutput.Add(stdOutput.Data);
    }
}
share|improve this answer
    
This is a very good idea, because if you do it this way the script ALWAYS runs outside of ArcMap, so you only have one environment to test in. –  Jason Scheirer Mar 15 '12 at 23:06
    
+1 I was doing something similar to this, but no where near as elegant or functional. I really like the returning of the values from Python back to .NET. One trick with launching a wxPython GUI window though, you have to call pythonw.exe to avoid getting a command window. Thanks for the valuable input. –  Chad Cooper Mar 16 '12 at 13:39
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.