1

Consider the following Jupyter notebook Python code:

%matplotlib widget
import matplotlib.pyplot as plt
from ipywidgets import widgets, Layout
from IPython.display import display

out_widget_plot = widgets.Output()
with out_widget_plot:
    with plt.style.context("default"): # ggplot
        fig, (ax1) = plt.subplots(1, 1)

fig.suptitle('test title', fontsize=10) 
tline = ax1.plot([0,1,2], [10,20,30])
fig.tight_layout()

the_ui = widgets.VBox([ widgets.HTML("<b>Hello</b>"), out_widget_plot, widgets.HTML("<b>World</b>"),])
display(the_ui)

When I run this in a Jupyter notebook, I get:

jupyter-output

The vertical toolbar seems to be outside of the matplotlib plot area itself. So my questions are:

  • Can I somehow move the toolbar so it is over the matplotlib plot area - and it is laid out horizontally (as indicated on the image)?
  • Can I also move the "x=... y=..." bottom indicator, so it is also placed over the matplotlib plot area?

PS: Otherwise, I would also like to suppress the "Figure 1" title - but I guess this topic Removing tool bar and figure title when using jupyter-matplotlib answers that alerady ...

sdbbs
  • 4,270
  • 5
  • 32
  • 87

1 Answers1

1

Well, this was a short joy; as of ipympl 0.8.4, the below hack does not work anymore: Getting back toolbar on left (if set to top position) in 0.8.4? · Issue #411 · matplotlib/ipympl - so the work I put in to get the hack working is wasted now. Such is the world - things never get better, and everything rots and goes to shit; just an endless waste of time ...


Well, I managed to do something - it basically comes from the realization, that the toolbar and the plot have their own separate divs, and then realizing (via How would you make two <div>s overlap?) that they can be placed on top of one another using CSS position: absolute.

In any case, if there is a better solution, I'd love to hear it. Here is the code:

%matplotlib widget
import matplotlib.pyplot as plt
from ipywidgets import widgets, Layout
from IPython.display import display, HTML

# the below CSS style override in Jupyter, allows the div that hosts the Matplotlib toolbar, to be placed "on top" of the div that hosts the plot:
# widget-label does the same, but for the bottom "x/y" indicator (which is why its position needs to also be controlled with margin)
HTML("""
<style>
.jupyter-matplotlib-toolbar {
    overflow: visible;
    position: absolute;
    z-index: 1000;
}
.widget-label {
    color: var(--jp-widgets-label-color);
    font-size: var(--jp-widgets-font-size);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: var(--jp-widgets-inline-height);
    z-index: 1000;
    margin-top: 465px;
    margin-left: 291px;
}
</style>
""")

out_widget_plot = widgets.Output()
with out_widget_plot:
    with plt.style.context("default"): # ggplot
        fig, (ax1) = plt.subplots(1, 1)

fig.suptitle('test title', fontsize=10) 
tline = ax1.plot([0,1,2], [10,20,30])
fig.tight_layout()
#fig.canvas.toolbar.button_style = 'info' # test: ok, works (but don't need it here)
#fig.canvas.toolbar.orientation = 'horizontal' # no error, but no effect either
fig.canvas.toolbar_position = 'top' # this also switches the orientation to horizontal, too
fig.canvas.header_visible = False # Gets rid of "Figure 1" on top

the_ui = widgets.VBox([ widgets.HTML("<b>Hello</b>"), out_widget_plot, widgets.HTML("<b>World</b>"),])
display(the_ui)

This is the output - note that you can right-click the plot once, and you will get that thin blue outline indicating the size of the plot element - and which ultimately shows, that the toolbar and the 'x/y' label are now on top of the plot element:

jupyter-output


EDIT: In another code I've had, the above with HTML(""" ... """) failed; so what worked for me there, was to output the HTML via widgets.HTML, like this:

%matplotlib widget
import matplotlib.pyplot as plt
from ipywidgets import widgets, Layout
from IPython.display import display, HTML

out_widget_plot = widgets.Output()
with out_widget_plot:
    with plt.style.context("default"): # ggplot
        fig, (ax1) = plt.subplots(1, 1)

fig.suptitle('test title', fontsize=10) 
tline = ax1.plot([0,1,2], [10,20,30])
fig.tight_layout()
#fig.canvas.toolbar.button_style = 'info' # test: ok, works (but don't need it here)
#fig.canvas.toolbar.orientation = 'horizontal' # no error, but no effect either
fig.canvas.toolbar_position = 'top' # this also switches the orientation to horizontal, too
fig.canvas.header_visible = False # Gets rid of "Figure 1" on top

# the below CSS style override in Jupyter, allows the div that hosts the Matplotlib toolbar, to be placed "on top" of the div that hosts the plot:
# widget-label does the same, but for the bottom "x/y" indicator (which is why its position needs to also be controlled with margin)
sthtml = """
<style>
.jupyter-matplotlib-toolbar {
    overflow: visible;
    position: absolute;
    z-index: 1000;
}
.widget-label {
    color: var(--jp-widgets-label-color);
    font-size: var(--jp-widgets-font-size);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: var(--jp-widgets-inline-height);
    z-index: 1000;
    margin-top: -41px;
    margin-left: 58px;
}
</style>
"""

the_ui = widgets.VBox([ widgets.HTML(sthtml), widgets.HTML("<b>Hello</b>"), out_widget_plot, widgets.HTML("<b>World</b>"),])
display(the_ui)
sdbbs
  • 4,270
  • 5
  • 32
  • 87