widgetti/reacton

Matplotlib plots not rendering properly in output widgets.

Closed this issue · 4 comments

When using an ipywidgets.Output widget in a reacton component, plots are not displayed in notebook. I've tested this with the ipympl and inline backends. It works fine when using ipywidgets directly, and used to work with react-ipywdgets 0.11.

Here's an example that shows both the working case (with ipywidgeds) and the non-working case (reacton).

import matplotlib.pyplot as plt
import reacton as react
import reacton.ipywidgets as w
import ipywidgets as widgets

#%matplotlib inline
%matplotlib ipympl

def plot(outputWidget):
    with plt.ioff():
        fig, ax = plt.subplots()

        fruits = ['apple', 'blueberry', 'cherry', 'orange']
        counts = [40, 100, 30, 55]
        bar_labels = ['red', 'blue', '_red', 'orange']
        bar_colors = ['tab:red', 'tab:blue', 'tab:red', 'tab:orange']

        ax.bar(fruits, counts, label=bar_labels, color=bar_colors)

        ax.set_ylabel('fruit supply')
        ax.set_title('Fruit supply by kind and color')
        ax.legend(title='Fruit color')

        with outputWidget:
            print("Displaying")
            plt.show()


# Reacton Test Case
@react.component()
def Test():
    render, setRender = react.use_state(False)
    
    def displayReacton():
        if render == False:
            return
        
        outputWidget = react.get_widget(output)
        plot(outputWidget)
    
    with w.VBox() as vbox:
        w.Button(description="Render", on_click=lambda: setRender(True))
        output = w.Output()
        
    react.use_effect(displayReacton, [render])
    
    return vbox

Test()

# Ipywidgets test case
outputWidget = widgets.Output()
button = widgets.Button(description="Render")

def displayIpywidgets(_):
    plot(outputWidget)

button.on_click(displayIpywidgets)

widgets.VBox([
    button,
    outputWidget
])

Software Versions:

python                          3.10.9
matplotlib-base           3.7.1
ipympl                           0.9.3
reacton                          1.2.2

Thanks for the great bug report.

Note that we now automatically capture anything in the render phase to an output widget that is using the display mechanism. E.g. you could do:

...
        ax.legend(title='Fruit color')
#         with outputWidget:
        plt.show()
...
    with w.VBox() as vbox:
        if render:
            plot(None)
        w.Button(description="Render", on_click=lambda: setRender(True))
        
#     react.use_effect(displayReacton, [render])

See https://solara.dev/api/display

Awesome! Thanks for the quick response. I've tested against master, and it seems to fix the issue. The version in conda-forge (1.3.2) still has the bug though, I assume 1.3.3 will be released soonish?

merged it 10 seconds ago conda-forge/reacton-feedstock#14 :)

It can take up to an hour to be available.

Thanks! 1.3.3 from conda-forge resolves the issue.