Gnome shell extension: how to do change panelMenu button icons?

I want to change the panel icon to reflect changes in state.
This means I have two svg icons, and I want to change between them.
When the panel is being constructed, I create two st.Icon objects and save a global reference to them on the extension object, as well as the button object. Based on the state, I set the icon, which works when the shell starts. I always get the correct icon.

This is what I do when constructing the panel:

// ext is the extension object
    this.button = new Button(0.0, _("an extension"));
            ext.button = this.button;
            ext.button_icon_auto_on = new St.Icon({
                gicon: Gio.icon_new_for_string(`${Me.path}/icons/auto-on-symbolic.svg`),
                style_class: "system-status-icon",
            });
            ext.button_icon_auto_off = new St.Icon({
                gicon: Gio.icon_new_for_string(`${Me.path}/icons/auto-off-symbolic.svg`),
                style_class: "system-status-icon",
            });

then a few lines later based on the state, I do

this.button.icon = ext.button_icon_auto_on;

or the other one.

This is definitely working: I always get the correct icon when the shell starts.

Later, in an extension method to handle the keyboard shortcut for state toggling, I try again:

this.button.icon = this.button_icon_auto_off;  //here, 'this' is the extension object

but this time, I don’t see any change to the panel icon.

Button is an extension of st.Widget but I can’t see any method that looks like it is a better way of updating the icon than assigning to it, but I don’t understand how this would trigger the shell to refresh the icon.

this sounds like it may be related, but it didn’t help me:

I suspect that “Button” is a subclass of PanelMenu.Button, but it’s impossible to tell without code. PanelMenu.Button doesn’t have an icon property, so a lot depends on that code :wink:

My guess would be that what you want is something like

    this.button.icon.gicon = this._iconAutoOn;  // a Gio.Icon, not St.Icon

That is about GTK, which is an application toolkit. Extensions (and gnome-shell itself) use St (shell-toolkit) which often uses similar patterns as GTK, but cannot be used interchangeably.

And to make it even more confusing, PanelMenu.Button isn’t the same as St.Button :confused:

You sir are a legend.
I save the GIO icons (only one shown):

 // setting up the panel
// ext is the extension object, used in this case case to save the icons as a 'global'

  ext.button_gio_icon_auto_on = Gio.icon_new_for_string(`${Me.path}/icons/pop-shell-auto-on-symbolic.svg`);

....

let button_icon_auto_on = new St.Icon({
            gicon: ext.button_gio_icon_auto_on ,
            style_class: "system-status-icon",
        });
...
if (ext.settings.tile_by_default()){
            this.button.icon = button_icon_auto_on;
        } else {
            this.button.icon = button_icon_auto_off;
        }

// the extension object has a method to handle the state toggling, by keyboard shortcut or interaction with panel toggle switch

// set the icon
 this.button.icon.gicon = this.button_gio_icon_auto_off; // type: Gio.Icon