【问题标题】:Jupyter matplotlib widget: place toolbar horizontally over plot?Jupyter matplotlib 小部件:将工具栏水平放置在绘图上?
【发布时间】:2021-11-05 10:59:00
【问题描述】:

考虑以下 Jupyter notebook Python 代码:

%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)

当我在 Jupyter 笔记本中运行它时,我得到:

垂直工具栏似乎在 matplotlib 绘图区域本身之外。所以我的问题是:

  • 我能否以某种方式移动工具栏,使其位于 matplotlib 绘图区域上方 - 并且水平布局(如图所示)?
  • 我是否也可以移动“x=... y=...”底部指示器,使其也放置在 matplotlib 绘图区域上方?

PS:否则,我也想取消“图 1”标题 - 但我猜这个主题 Removing tool bar and figure title when using jupyter-matplotlib 回答了这个问题......

【问题讨论】:

    标签: python matplotlib jupyter-notebook ipywidgets


    【解决方案1】:

    嗯,这是一个短暂的快乐;从 ipympl 0.8.4 开始,以下 hack 不再起作用:Getting back toolbar on left (if set to top position) in 0.8.4? · Issue #411 · matplotlib/ipympl - 所以我为使 hack 工作而投入的工作现在被浪费了。世界就是这样——事情永远不会变得更好,一切都会腐烂,一团糟;只是无休止地浪费时间......


    好吧,我设法做了一件事——它基本上来自于意识到工具栏和绘图有自己独立的 div,然后意识到(通过How would you make two <div>s overlap?)它们可以使用CSS position: absolute.

    无论如何,如果有更好的解决方案,我很乐意听到。代码如下:

    %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)
    

    这是输出 - 请注意,您可以右键单击绘图一次,您将获得指示绘图元素大小的细蓝色轮廓 - 最终显示工具栏和“x/y”标签现在位于绘图元素的顶部:


    编辑:在我拥有的另一个代码中,上面带有HTML(""" ... """) 的代码失败了;所以在那里对我有用的是通过widgets.HTML输出HTML,如下所示:

    %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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-10
      • 2015-09-17
      • 1970-01-01
      • 2014-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      相关资源
      最近更新 更多