There's no "-icon" option for a button object, did you mean "-image"?
The problem with this method is that it is not documented to maintain a
pixel size (which appears to be what Mark wants, pixel size of button
does not change).
The button man page says (emphasis added here):
[-width width] Specifies a desired width for the button. If an
image or bitmap is being displayed in the button then the value
is in screen units (i.e. any of the forms acceptable to
Tk_GetPixels). *For a text button (no image or with -compound
none) then the width specifies how much space in characters to
allocate for the text label.*
And the options man page says (emphasis added here):
[-image image] Specifies an image to display in the widget, which
must have been created with the image create command.
Typically, if the -image option is specified then it overrides
other options that specify a bitmap or textual value to display
in the widget, though this is con- trolled by the -compound
option; *the -image option may be reset to an empty string to
re-enable a bitmap or text display.*
So the documented behavior of empty string to "-image" is to return to
text character sizing, and the pixel width of "winfo width .b" in text
characters is from the pixel width of the same in pixels.
Since Mark appears to want to show/hide images on buttons, his easiest
method to maintain an identical pixel size for the button [1] is to
swap the active image with a blank image of the same size rather than
toggling between text display and image display modes for the buttons.
[1] Yes, the geometry manager could also be forced into enforcing a
size as well, but one more AxB size blank image solves all the problems
with little fussing.