【问题标题】:How do you automatically update matplotlib subplot limits based on another's limits within Tkinter?如何根据 Tkinter 中其他人的限制自动更新 matplotlib 子图限制?
【发布时间】:2018-04-12 02:05:57
【问题描述】:

我在 Tkinter 画布中有两个 matplotlib 子图,绘制相同的数据,使用 Matplotlib NavigationToolbar2TkAgg 按钮供用户导航子图等。我想让顶部面板显示数据的一个区域(xlimits x1 到x2),而底部面板会根据用户在任一面板中的缩放/平移方式自动显示数据与该区域的偏移量(xlimits:x1+offset 到 x2+offset)。我本质上是在 Tkinter 中寻找 sharex/sharey 行为,但限制值由一些简单的函数操纵。有没有办法捕获发生触发简单功能的 NavigationToolbar 事件;还是我走错了路?

【问题讨论】:

    标签: python user-interface matplotlib tkinter


    【解决方案1】:

    您可以根据另一个图的轴范围为一个图设置新的轴范围。在两个轴上使用 xlim_changed 事件调用一个函数,该函数根据当前限制调整另一个绘图的限制。
    需要确保在更改限制之前断开事件的连接,以免陷入无限循环。

    下面是一个实现,其中底部图与顶部图相比移动了 100 个单位。

    import numpy as np; np.random.seed(1)
    import matplotlib.pyplot as plt
    
    x = np.linspace(0,500,1001)
    y = np.convolve(np.ones(20), np.cumsum(np.random.randn(len(x))), mode="same")
    
    fig, (ax, ax2) = plt.subplots(nrows=2)
    
    ax.set_title("original axes")
    ax.plot(x,y)
    ax2.set_title("offset axes")
    ax2.plot(x,y)
    
    offset         = lambda x: x + 100
    inverse_offset = lambda x: x - 100
    
    class OffsetAxes():
        def __init__(self, ax, ax2, func, invfunc):
            self.ax = ax
            self.ax2 = ax2
            self.func = func
            self.invfunc = invfunc
            self.cid = ax.callbacks.connect('xlim_changed', self.on_lims)
            self.cid2 = ax2.callbacks.connect('xlim_changed', self.on_lims)
            self.offsetaxes(ax, ax2, func)  
    
        def offsetaxes(self,axes_to_keep, axes_to_change, func):
            self.ax.callbacks.disconnect(self.cid)
            self.ax2.callbacks.disconnect(self.cid2)
            xlim = np.array(axes_to_keep.get_xlim())
            axes_to_change.set_xlim(func(xlim))
            self.cid = ax.callbacks.connect('xlim_changed', self.on_lims)
            self.cid2 = ax2.callbacks.connect('xlim_changed', self.on_lims)
    
        def on_lims(self,axes):
            print "xlim"
            if axes == self.ax:
                self.offsetaxes(self.ax, self.ax2, self.func)
            if axes == self.ax2:
                self.offsetaxes(self.ax2, self.ax, self.invfunc)
    
    o = OffsetAxes(ax, ax2, offset, inverse_offset)
    
    
    plt.show()
    

    【讨论】:

    • 您可以在调用 set_xlim 时使用 emit=False 来防止递归,无需断开/重新连接
    猜你喜欢
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 2021-10-09
    • 2022-10-21
    • 1970-01-01
    相关资源
    最近更新 更多