Script.toggle_icon(new_state) changes the icon size

Hey everyone!

I am using a smart button. During selfinit the icon is set with this function:
ui_button_cmp.set_icon(path_to_image, icon_size=32)

And then when the user hanges the button state (by clicking on it) i use this code:
script.toggle_icon(new_state)

So that default “on.png”/“off.png” icons are used. And everything works fine, but the button becomes smaller:
image

Is there a way to specify the size i want? I mean is it accessible through “script” namespace? Because after the button is initiated, there is no longer acces to button’s ui guid.

both icons have the same size in png?

1 Like

yes, of course. Even when i switch the button state twice (so that the state returns to the initial one) - the icon never gets bigger again

I don’t see your code and don’t use this feature but, maybe try to return on.png ui button or maybe your script processing all the time after pick and you should swich off the whole process?

1 Like

Here’s a piece of scipt.py file, which is contained in swing_direction.smartbutton folder:

import pickle as pl
import os.path as op

from pyrevit import script

#this function is called when the Revit app starts:
def __selfinit__(script_cmp, ui_button_cmp, __rvt__):
    #here i'm getting current_state variable (True or False) to define 
    #whether the button should be activated or not
    with open(get_datafile(), 'rb') as f:
        current_state = pl.load(f)
    if current_state:
        path_to_image = op.join(op.dirname(op.realpath(__file__)),"on.png")
        ui_button_cmp.set_icon(path_to_image, icon_size=32)

#this happens when the button is pressed:
if __name__ == '__main__':
    with open(get_datafile(), 'rb') as f:
        current_state = pl.load(f)
    new_state = not current_state
    script.toggle_icon(new_state)

Also: when i am initiating the button as usual (with no ui_button_cmp.set_icon(path_to_image, icon_size=32)), the result is the same: after script.toggle_icon(new_state) the icon just gets smaller.

I’ve tried to make the icon size bigger (128x128px), but i’ve started getting such Warning:

**WARNING** [pyrevit.coreutils.ribbon] Icon file is too large. Large icons adversely affect the load time since they need to be processed and adjusted for screen scaling. Keep icons at max 96x96 pixels: Z:\__StandardyBIM\07_pyExtensions\pyPlus3.extension\pyPlus3.tab\P3_Doors&Windows.panel\swing_direction.smartbutton\on.png

as far as I know max size is 96px for icons

yes, it is, but the icon size jumps either when the icon size is 96 or 128 or 64

Have you tried to reuse the code behind the MinifyUI for example to try with your on/off icons?
I did try it myself in a stack and in a regular position with no issue.
2022-10-11_12-51-26

The main difference I noticed with your code is the use of ICON_MEDIUM sizing:

from pyrevit.coreutils.ribbon import ICON_MEDIUM

def __selfinit__(script_cmp, ui_button_cmp, __rvt__):
    off_icon = script_cmp.get_bundle_file('off.png')
    ui_button_cmp.set_icon(off_icon, icon_size=ICON_MEDIUM)
1 Like

from pyrevit/coreutils/ribbon.py library

    def set_icon(self, icon_file, icon_size=ICON_MEDIUM):
        try:
            button_icon = ButtonIcons(icon_file)
            rvtapi_obj = self.get_rvtapi_object()
            rvtapi_obj.Image = button_icon.small_bitmap
            if icon_size == ICON_LARGE:
                rvtapi_obj.LargeImage = button_icon.large_bitmap
            else:
                rvtapi_obj.LargeImage = button_icon.medium_bitmap
            self._dirty = True
        except Exception as icon_err:
            raise PyRevitUIError('Error in applying icon to button > {} : {}'
                                 .format(icon_file, icon_err))

size is ICON_SMALL, ICON_MEDIUM or ICON_LARGE like @ burger king :grinning_face_with_smiling_eyes:

2 Likes

Many thanks!

I didn’t work with ICON_MEDIUM, and it’s weak that script.toggle_icon(new_state) doesn’t have icon_size argument, so i’ve written my own function to toggle button state, which basically is a copy of native pyrevit’s function:

def change_button_state(new_state):

    all_buttons = script.get_all_buttons()

    if new_state==True: button_file_name = "on.png"
    else: button_file_name = "off.png"

    for uibutton in all_buttons:

        path_to_image = op.join(op.dirname(op.realpath(__file__)),button_file_name)
        uibutton.set_icon(path_to_image, icon_size=ICON_LARGE)
1 Like