What about that: embed your Python script into a Python script tool inside a custom toolbox. Extent your add-in with a button. If the user clicks the button, the add-in runs the script tool (synchron) and after it finished, it does the other stuff with ArcObjects. For deployment (to the assembly cache) you can add the custom toolbox as a resource to the add-in. The code for using an embedded toolbox is something like that:
// Initialize the geoprocessor.
IGeoProcessor2 gp = new GeoProcessorClass();
// Add the toolbox.
string strPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string strToolbox = strPath + "\\PythonTools.tbx";
gp.AddToolbox(strToolbox);
// Generate the array of parameters.
IVariantArray parameters = new VarArrayClass();
parameters.Add(inString);
// Execute the model tool by name.
IGeoProcessorResult result = gp.Execute("Reply", parameters, null);
// Ergebnis zurückliefern
string reply = result.GetOutput(0).GetAsText();
I want to know if it is possible to create an Add-in extension that listens for map refresh events to specifically respond to the actions of a python script?
I envision adding a hidden text object into a specific kind of map that will at first indicate to the Add-in Extension that nothing needs to be done. When the Python script runs it will write to that text object to set a flag telling the Extension that it is processing a change to the map, so ignore any map refresh actions during the script processing. Just prior to completion of the Python script, the Python script will update the Text Object to say that it just finished and needs the Extension to do its thing. Then the Python script will refresh the map. I assume the Add-in Extension can detect the map refresh event triggered by the Python script, read the text object to detect that python wants the extension to run and then the extension can fire its action on the map. When the extension finishes it will reset the text object back to the state indicating that nothing needs to be done by the extension.
Does this sound like it will work?
I want the Add-in to detect when arcpy.mapping finishes updating everything that it can in the map, and then have the extension change the data frame clipping geometry to match a feature's shape according to the current definition query on a layer that the python script set. I do not want the user to have to push another button after the Python script finishes to do things that Python seemingly cannot do, and I do not want the Add-in to do the Python script actions. I do not see any other way to have Python trigger an ArcObjects action within the currently open map, since the ctypes functionality says it is limited to basic C++ types and I do not see a way to pass a hook for the current map to an ArcObjects DLL method from Python.
Please correct me if I am wrong about any of this or if there is a better approach to do what I want.
My python script tool is unconventional and is not merely designed to act as a geoprocessing tool. It acts like a form object with user interface capabilities. I do not want the user to simply feed parameters to the tool. I intend for them to interact with the tool. I am aware that with .Net I could design a form using ArcObjects, but I have no interest in doing that.
At first thought, your pattern sounds like the observer pattern, notify registered observers when an event occurs, except you're using two different languages, so I'm not sure how you would connect the two.
At second thought, there is: com.esri.arcgis.carto.IActiveViewEventsFocusMapChangedEvent Which might work.
Lastly, Add-ins respond to user initiated events, so I'm not sure how you would initiate the tool, button, menu, utility object or extension that should be listening for the events from python.
Can I interest you in writing a Java add-in? 😄
// Create an instance of DecimalFormat to limit the number of integers the user can type into certain fields. DecimalFormat temperatureFormat = new DecimalFormat("##0.00"); ftfTemperature = new JFormattedTextField(new DefaultFormatterFactory(new NumberFormatter(temperatureFormat),new NumberFormatter(temperatureFormat),new NumberFormatter(temperatureFormat))); ftfTemperature.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { ftfTemperature.selectAll(); } }); } }); ftfTemperature.setBounds(120, 8, 85, 20); panel.add(ftfTemperature);
What if you wrote a console ArcObjects application that you execute from python? I believe you can get a list of current ArcMap application references from the IAppROT interface. That might work.