Question about OnChanged in Python Command production

Hello, everyone.
Here’s the situation, I added multiple OnChanged in my Command (python), and when I actually run it I find that only the first OnChanged is available, the other buttons don’t trigger the appropriate function even if they are clicked, I even tried changing the OnChanged event of the other buttons to the only one that’s currently available I even tried to change the OnChanged events of the other buttons to the only currently available button, but it still doesn’t work.
What is the cause of this problem?

Could you post the code? It sounds weird.

Of course you can, here is some of the relevant code:

def OnStart():
    global cmd_button,cmd_plane,cmd_str
    cmd_plane = cmd.getProperty('Plane')
    if not cmd_plane:
        cmd_str = cmd.createProperty(VC_STRING,'kind',VC_PROPERTY_STEP)
        cmd_str.StepValues = ['other', 'Scara', '6-Axis']
        cmd_button = cmd.createProperty(VC_BUTTON,'Set')
        cmd_actionbutton = cmd.createProperty(VC_BUTTON,'actionbutton')
        cmd_rebutton = cmd.createProperty(VC_BUTTON,'reload_demo')
    cmd_str.OnChanged = choose
    cmd_str.Value = '6-Axis'
    cmd_button.OnChanged = OnUseSelectedComponent
    cmd_rebutton.OnChanged = ResetScript
    cmd_actionbutton.OnChanged = OnUseSelectedComponent
    
    executeInActionPanel()
def OnUseSelectedComponent(*n):
    global comp,cmd_str
    sel = app.SelectionManager.getSelection(VC_SELECTION_COMPONENT)
    if sel:
      if len(sel) > 1:
        print 'Warning: Multiple components selected. Select only one component.'
      else:
        comp = sel[0]
        if cmd_str.Value == '6-Axis':
            CreateRobot_six()
        elif cmd_str.Value == 'Scara':
            CreateRobot_Scara()
        elif cmd_str.Value == 'other':
            CreateRobot_other()
def ResetScript (*n):
    print 'reload ok!'
    app.findCommand('CreateRobot').recompile()

I tried to generate three buttons, cmd_button, cmd_actionbutton, cmd_rebutton, but only the button cmd_button is available, I changed the OnChanged of the cmd_actionbutton to OnUseSelectedComponent as well, but it doesn’t allow the code to trigger when clicking on the cmd_actionbutton.

You need to set the button property as global variables.

global cmd_button,cmd_plane,cmd_str

to

global cmd_button,cmd_plane,cmd_str, cmd_rebutton, cmd_actionbutton
1 Like

Okay, thank you very much chungmin!
If you can, can you give me a little insight into why, I’m sorry I haven’t touched it in a while (this code was first written by me in September 2023), it may be that it’s a very simple part of the code, but I may have forgotten about it. :rofl:

If a Python API wrapper object goes out of Python script’s scope it gets garbage collected and it can no longer do your event callback.

So generally you need to “store” all objects from where you want to get events somewhere in global scope of your script. It can be individual variables or a list or anything that keeps them alive, really.

3 Likes

Very much your explanation, it helps me a lot! :grinning:

Hy,

do .Net-AddIns behave same?

Regards

Actually I’m not 100% sure but I think .NET wrapper lifetime is tied to the native object underneath such that even if you don’t hold a reference to the wrapper anywhere you probably still get the event callback.
It is anyway a good practice to retain references to the wrappers you are using one way or another.

This is also why it is very important to unsubscribe from events in .NET because any event source will keep the event subscribers alive, which is a common way to cause memory leaks and unexpected behavior in .NET code.

2 Likes