How do you refresh view in ArcMap from Python?

3961
5
01-17-2011 06:48 PM
DarrenSmith
New Contributor III
Hi,

(originally posted on ArcGIS Desktop - General)
I've written a Python script in 9.3.1 which as its result selects a set of features (SelectLayerByAttribute) for a layer visible in ArcMap. However, the selected features are only visible once the user performs an action that results in a refresh. Is there some way (a work around of some type) to force a view refresh from within Python (in 9.3.1 & not 10)?

Cheers,

Darren
Tags (2)
0 Kudos
5 Replies
BradPosthumus
Occasional Contributor II
There is indeed a workaround. You can refresh the screen using ArcObjects, which fortunately can be accessed in Python by using comtypes. It's a bit of work but for those of us still mired in 9.3 it can be a godsend.

You can create a script tool from the code below (1st parameter = Layer, 2nd parameter = SQL Expression). It will select features from your layer and then refresh the active view.

One note here is the comtypes code isn't directly hooked into the current ArcMap session, so it has to loop through all open ArcGIS sessions to find ArcMap. If you have multiple ArcMap sessions open, this code will actually refresh the view in all of them. You could adjust the script to find a specific session by comparing the MXD name with the first part of objApplication.Caption and then break from the loop when it matches.

Comtypes can be downloaded from here: http://sourceforge.net/projects/comtypes/files/comtypes/0.6.2/comtypes-0.6.2.win32.exe/download

import arcgisscripting
gp = arcgisscripting.create()

strLayer = gp.GetParameterAsText(0)
strExpression = gp.GetParameterAsText(1)

gp.SelectLayerByAttribute_management(strLayer, "NEW_SELECTION", strExpression)

import comtypes.client

# Load the required COM libraries
esriFramework = comtypes.client.GetModule(r'C:\Program Files\ArcGIS\com\esriFramework.olb')
esriArcMapUI = comtypes.client.GetModule(r'C:\Program Files\ArcGIS\com\esriArcMapUI.olb')

# Create the AppROT object which contains all open ArcGIS applications
objAppROT = comtypes.client.CreateObject(esriFramework.AppROT, interface=esriFramework.IAppROT)

# Loop through each open ArcGIS application
for i in range(objAppROT.Count):

    # Query interface (convert) the current item in the list to something we can work with.
    objApplication = objAppROT.Item(i).QueryInterface(esriFramework.IApplication)

    # Check to see if the current ArcGIS application is ArcMap.
    if objApplication.Name == "ArcMap":

        # Get the current document in the ArcMap application.
        objMxDocument = objApplication.Document.QueryInterface(esriArcMapUI.IMxDocument)

        # Refresh the active view.
        objMxDocument.ActiveView.Refresh()
        gp.addmessage("View refreshed...")

del objAppROT 
0 Kudos
BradPosthumus
Occasional Contributor II
Here's a better way that accesses the current ArcMap session directly:

import arcgisscripting
gp = arcgisscripting.create()

strLayer = gp.GetParameterAsText(0)
strExpression = gp.GetParameterAsText(1)

gp.SelectLayerByAttribute_management(strLayer, "NEW_SELECTION", strExpression)

import comtypes.client
# Load the required COM libraries
esriFramework = comtypes.client.GetModule(r'C:\Program Files\ArcGIS\com\esriFramework.olb')
esriArcMapUI = comtypes.client.GetModule(r'C:\Program Files\ArcGIS\com\esriArcMapUI.olb')

# Get the current ArcMap session
objApplication = comtypes.client.CreateObject(esriFramework.AppRef, interface=esriFramework.IApplication)
objMxDocument = objApplication.Document.QueryInterface(esriArcMapUI.IMxDocument)
objMxDocument.ActiveView.Refresh()
gp.addmessage("View refreshed...")


I found this solution, as well as some excellent wrapper code and discussion, at this link:

http://gis.stackexchange.com/questions/5017/python-comtypes-and-arcobjects-error-creating-approt-obj...
0 Kudos
DarrenSmith
New Contributor III
Thanks for both of your replies Brad.

I've come up with the following modified function based on code found in the link you gave. However, as I'm working on a distributed geoprocessing tool I still have two problems with my current solution:

1) I'm guessing the registry keys change for each release? i.e. the typelib key in the example given for 10 from the link (for the esriFramework OLB) was actually the key for esriGlobeCore.Globe on my install (9.3.1).

2) This approach will only work for Windows.

def refreshArcMap():
    """
    Refreshes view in current ArcMap session.
    Assumptions: Python comtypes framework installed & comtypes.client already imported 
    Limitations: Only works on Windows & only tested for ArcGIS 9.3.1 (32-bit).
    """
    try:
    
        import _winreg

        # Look in registry for the TypeLib entry for the esriFramework OLB 
        keyESRI = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, \
                                  r"TypeLib\{866AE5D3-530C-11D2-A2BD-0000F8774FB5}\1.0\HELPDIR") 
        # Get path of ArcGIS type libraries as string from registry e.g "C:\Program Files\ArcGIS\com" 
        comDir =_winreg.QueryValueEx(keyESRI, None)[0] 

        # Load the required COM libraries
        esriFramework = comtypes.client.GetModule(comDir + r'\esriFramework.olb')
        esriArcMapUI = comtypes.client.GetModule(comDir + r'\esriArcMapUI.olb')

        # Get the current ArcMap session & refresh view
        objApplication = comtypes.client.CreateObject(esriFramework.AppRef, interface=esriFramework.IApplication)
        objMxDocument = objApplication.Document.QueryInterface(esriArcMapUI.IMxDocument)
        objMxDocument.ActiveView.Refresh()
        gp.AddMessage("View refreshed...")

    except Exception, ErrorDesc:
        # If an error occurred while refreshing instruct user to manually refresh
        gp.AddWarning("A problem occured when trying to automatically refresh ArcMap!")
        gp.AddWarning("Perform a manual refresh of map window (i.e. click 'Refresh View' button at the bottom of the map window) to view results")
0 Kudos
BradPosthumus
Occasional Contributor II
Thanks for both of your replies Brad.

1) I'm guessing the registry keys change for each release? i.e. the typelib key in the example given for 10 from the link (for the esriFramework OLB) was actually the key for esriGlobeCore.Globe on my install (9.3.1).

2) This approach will only work for Windows.


(Delayed response.....)

  1. I suppose you would need to roll out a new version of your tool when ArcGIS 10 comes online for your users (though it would be a pain to maintain two versions if some are still in 9.3). Once in 10 you may want to rewrite it using ArcPy, though it may not be robust enough for your requirements.


  2. If it's for ArcGIS desktop you're limited to Windows anyway.

0 Kudos
DarrenSmith
New Contributor III
Thanks again Brad, am sure looking forward to moving to 10 & ArcPy.
0 Kudos