0

I am defining an ipywidget button with the objective to run a function when the user clicks on it:

import ipywidgets as widgets

Button = widgets.Button(description='Search', disabled=False, button_style='info', tooltip='Search')
display(Button)

def whenclick(b):
    if catalogue.selected_index+1 ==2:
        dfS2 = pd.DataFrame({'Name': nameS2})
        print(dfS2)

Button.on_click(whenclick)

Where nameS2 is:

['S2A_MSIL2A_20191205T110431_N0213_R094_T30TVK_20191205T123107.zip',
 'S2B_MSIL2A_20191203T111329_N0213_R137_T30TVL_20191203T123004.zip']

This code works in the way that when clicking on the button dfS2 gets printed since I am using the print command. However, I want to display the dataframe as variable (witouth calling `print).

def whenclick2(b):
    if catalogue.selected_index+1 ==2:
        dfS2 = pd.DataFrame({'Name': nameS2})
        dfS2

Button.on_click(whenclick2)

When using this second option and clcking on the button, nothing gets delivered. I have tried to use return dfS2 for example, and many other apporaches (global variables, etc.) like :

if catalogue.selected_index+1 ==2:
    def whenclick(b):
        dfS2 = pd.DataFrame({'Name': nameS2})
        return dfS2

Button.on_click(whenclick)

But I always get no output when clicking my button. Any idea on this? I have been checking the examples in the ipywidget documentation but trying to simulate the same in my case did not work https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Events.html

-- EDIT --

Based on @skullgoblet1089 answers, I am trying the following code:

import ipywidgets as widgets

Button = widgets.Button(description='Search', disabled=False, button_style='info', tooltip='Search')
display(Button)

def whenclick2(b):
    global data_frame_to_print
    if catalogue.selected_index+1 ==2:
        dfS2 = pd.DataFrame({'Name': nameS2})
        data_frame_to_print = dfS2.copy()
        dfS2

Button.on_click(whenclick2)

However, when clicking on the button nothing gets displayed.

GCGM
  • 901
  • 1
  • 17
  • 38
  • Make the variable global using the `global` keyword. Or use a class to encapsulate class / instance level variables in the appropriate context. – skullgoblet1089 Dec 19 '19 at 15:46
  • @skullgoblet1089 could you please add a code example of your solution. New to python and not sure I completely get what you mean by encapsulate class. Thanks – GCGM Dec 19 '19 at 15:47

1 Answers1

1

Use the global keyword:

def whenclick2(b):
    global data_frame_to_print
    if catalogue.selected_index+1 ==2:
        dfS2 = pd.DataFrame({'Name': nameS2})
        data_frame_to_print = dfS2.copy()
        dfS2

Button.on_click(whenclick2)

It will declare (if not exist) and assign value to variable in global namespace for module.

skullgoblet1089
  • 554
  • 4
  • 12
  • I have tried your code (I have edited the question to show you exactly the code I run) and when clicking on the button, nothing gets displayed. Am I missing something? I am working on a Jupyter Notebook, in case this is relevant – GCGM Dec 19 '19 at 15:57
  • this code will give you a handle in global context that you can then use outside of the function call to print the variable to interactive console whenever you would like. i recommended this because i assumed that you wanted to interactively inspect the value of the df after the event in a different cell – skullgoblet1089 Dec 19 '19 at 18:12
  • I actually would like to run evertything on the same cell. When clicking on the button and, after that, calling `dfS2` in another code cell, I get `name dfS2 is not defined` error.... Am I missing something? – GCGM Dec 20 '19 at 12:20
  • Actually, I had tu add `return dfS2` in other to be able to call that variable in a new jupyter code cell. This is partially what I want, but the final objective would be to display `dfS2` when clicking on the button and not to needing to call the variable in a new cell. Any comments on this? – GCGM Dec 20 '19 at 13:33
  • Based on this other post - https://stackoverflow.com/questions/54813069/python-onclick-button-widget-return-object- it seems the solution of the `class` with be the option to go. Is that what you refered to in your comment @skullgoblet1089 – GCGM Jan 08 '20 at 15:12
  • Yes, notice how the use of a class can also help you "encapsulate" data in Python by assigning it as an attribute to a class instance. This way you can reference the data using the instance handle and attribute name as long as it is preserved in the appropriate (in your case global) context. – skullgoblet1089 Jan 08 '20 at 19:19
  • could you please provide a code example of your proposal? Not very familiar with `class` in python – GCGM Jan 13 '20 at 12:00
  • The link you shared is a great example of how to use class for your use case. – skullgoblet1089 Jan 13 '20 at 18:16
  • Actually, I have gave it a try and I am facing a small issue when I want to clean an output. Would you mind to have a look in case you are familiar with it? https://stackoverflow.com/questions/59719207/clean-output-whith-onclick-button-widget-python – GCGM Jan 14 '20 at 08:07