Select to view content in your preferred language

Can't set elementPositionX property on scalebar in a layout with arcpy

167
1
Jump to solution
04-24-2024 08:55 AM
Labels (1)
Brian_Wilson
Regular Contributor II

I need to select from a group of scalebars. For example, I have a 1 mile scale bar for scale 1:24000 and a bar set to feet for 1:1200)

I had similar code working in ArcMap. I am trying to port to ArcPro.

#Here is a snippet of the relevant code
        sb = self.find_scalebar(scale) # Using a scale 24000, find the scalebar element in the layout
        default_scalebar_element.visible = True
        if sb != default_scalebar_element:
            default_scalebar_element.visible = False # Hide the default
            # Move the desired scalebar into the layout
            sb.elementPositionY = x
            sb.elementPositionY = y
            sb.visible = True # Make sure it's visible
            print(scale, x, y, sb.elementPositionX, sb.elementPositionY)

Lines 7,8 SHOULD change the scalebar position. They don't, what gets printed in 10 is this

24000 21.87 16.6 26.18 16.6     <--- x value DID NOT CHANGE??

The scale bar is still off the printout, which is 18x24" so the above code successfully detects it needs to fix the scale (line 4), turns OFF the default scalebar but then fails to move the selected scalebar.

When running in a debugger, I can override the value after line 7 runs and push the value of X and voila! the scalebar appears. It's just lines 7,8 that fail.

WHY DOES IT FAIL? Very mysterious.

Running the script results in this

Brian_Wilson_0-1713973407933.png

 

Running the script in the debugger and manually setting X results in this; no code was changed.

4000 21.87 16.6 21.87 16.6    <--- value from print statement shows the new setting forced in

Brian_Wilson_1-1713973580278.png

To rule out unlikely interference from the debugger I ran it from the command line too. Still failed. I used ArcGIS Pro 3.2.2 and the standard unmodified conda environment arcgispro-py3

0 Kudos
1 Solution

Accepted Solutions
Brian_Wilson
Regular Contributor II

I found a workaround. Still no idea why setting X,Y fails but the workaround was pretty direct. I use CIM to copy the correct settings into the scalebar that shows on the map.

        default_scalebar_element = self.scalebars['Scalebar Default']
        sb = self.find_scalebar(scale)
        default_scalebar_element.visible = True
        if sb != default_scalebar_element:
            # Copy settings from desired scalebar
            sb_cim = sb.getDefinition("V3")
            df_cim = default_scalebar_element.getDefinition("V3")
            df_cim.unitLabel = sb_cim.unitLabel
            df_cim.units = sb_cim.units
            default_scalebar_element.setDefinition(df_cim)
            default_scalebar_element.elementWidth = sb.elementWidth

I want a non-programmer to be able to make changes to the scalebar settings without modifying the Python and I think this gets us close to that.

Setting the elementWidth in line 11 works for some reason 🙂 and is required so that the width of the bar works out to be exactly one mile.

View solution in original post

0 Kudos
1 Reply
Brian_Wilson
Regular Contributor II

I found a workaround. Still no idea why setting X,Y fails but the workaround was pretty direct. I use CIM to copy the correct settings into the scalebar that shows on the map.

        default_scalebar_element = self.scalebars['Scalebar Default']
        sb = self.find_scalebar(scale)
        default_scalebar_element.visible = True
        if sb != default_scalebar_element:
            # Copy settings from desired scalebar
            sb_cim = sb.getDefinition("V3")
            df_cim = default_scalebar_element.getDefinition("V3")
            df_cim.unitLabel = sb_cim.unitLabel
            df_cim.units = sb_cim.units
            default_scalebar_element.setDefinition(df_cim)
            default_scalebar_element.elementWidth = sb.elementWidth

I want a non-programmer to be able to make changes to the scalebar settings without modifying the Python and I think this gets us close to that.

Setting the elementWidth in line 11 works for some reason 🙂 and is required so that the width of the bar works out to be exactly one mile.

0 Kudos