(wxpython)将matplotlib NavigationToolbar设置为scrolledpanel内的图形静态

时间:2019-04-06 13:43:31

标签: python matplotlib wxpython

我有一个Matplotlib图,其中包含很多子图,需要>>> a = np.random.rand(3,4,6,7,8) >>> b = np.random.rand(4,5,9,10) >>> einsum_spreadout(a,b,a_axes=1,b_axes=0,a_spread_axis=2,b_spread_axis=2).shape (3, 5, 6, 7, 8, 9, 10) >>> b = np.random.rand(4,5,6,10) >>> einsum_spreadout(a,b,a_axes=(1,2),b_axes=(0,2),a_spread_axis=2,b_spread_axis=2).shape (3, 5, 7, 8, 10) >>> einsum_spreadout(a,b,a_axes=(1,2),b_axes=(0,2),a_spread_axis=4,b_spread_axis=4).shape (3, 7, 5, 10, 8) 。现在,我想要一个ScrolledPanel的图形,当图形navigation toolbar滚动时,它保持静态。 我尝试将其添加到画布父级之外的其他面板中,但这不起作用(导航工具栏仅保留在画布父级中)。
有什么方法可以使matplotlib导航工具栏保持静态,但使其余画布可滚动?
这是我完整的代码:

panel

import wx import wx.lib.scrolledpanel import matplotlib from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar from matplotlib.figure import Figure import wx.lib.inspection matplotlib.use('WXAgg') class PlotDemoApp(object): def __init__(self, data): self.app = wx.App() self.frame = PlotCanvas(None, -1, "PlotCanvas", data) self.frame.Show(True) wx.lib.inspection.InspectionTool().Show() self.app.MainLoop() class PlotCanvas(wx.Frame): def __init__(self, parent, wxid, title, data): wx.Frame.__init__(self, parent, wxid, title) self.box_main = wx.BoxSizer(wx.VERTICAL) panel_lower = wx.lib.scrolledpanel.ScrolledPanel(self, size=(2500,-1)) panel_lower.SetupScrolling() panel_lower.SetBackgroundColour("White") self.box_lower = wx.BoxSizer(wx.HORIZONTAL) box_local = wx.BoxSizer(wx.VERTICAL) plt = Figure(figsize=(95,10)) num_columns = len(data.columns) axes_1 = plt.add_subplot(1, num_columns, 1) data_numpy = data[data.columns[0]].to_numpy() depth = data.index.to_numpy() plt.gca().invert_yaxis() plt.subplots_adjust(left=0.01, right=1.00, top=0.95, bottom=0.05) axes_1.plot(data_numpy, depth) for i in range(1, num_columns): axes_tmp = plt.add_subplot(1, num_columns, i+1, sharey=axes_1) axes_tmp.set(xlabel=data.columns[i], ylabel='Depth', title='Depth vs ' + data.columns[i]) data_numpy = data[data.columns[i]].to_numpy() plt.gca().invert_yaxis() axes_tmp.plot(data_numpy, depth) canvas = FigureCanvas(panel_lower, -1, plt) canvas.draw() box_local.Add(canvas, 1, wx.EXPAND) panel_nav = wx.Panel(self) box_nav = wx.BoxSizer(wx.HORIZONTAL) toolbar = NavigationToolbar(canvas) box_nav.Add(toolbar) panel_nav.SetSizer(box_nav) toolbar.Realize() self.box_main.Add(panel_nav, 0, wx.CENTER) self.box_lower.Add(box_local, 1, wx.EXPAND) self.box_main.Add(panel_lower, 1, wx.EXPAND) panel_lower.SetSizer(self.box_lower) self.SetSizer(self.box_main) self.box_main.Layout() 这是一个熊猫数据框
样本数据:

data

1 个答案:

答案 0 :(得分:2)

希望这是您所追求的或至少指向正确的方向。

matplotlib导航工具栏似乎已焊接到绘图本身,但可以隐藏。

虽然它保持隐藏状态,但其功能仍然可用,因此我们可以创建自己的toolbar并在隐藏的工具栏中为其分配功能。

赞:

import wx
import wx.lib.scrolledpanel as scrolled
import pandas as pd
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
from matplotlib.figure import Figure

# images in /usr/share/matplotlib/mpl-data/images
# Your system may differ!

class PlotPanel(scrolled.ScrolledPanel):
    def __init__(self,parent):
        scrolled.ScrolledPanel.__init__(self, parent)
        self.SetupScrolling(scroll_x=True, scroll_y=True, scrollToTop=False, scrollIntoView=False)
        self.ShowScrollbars(True,True)
        self.plt = Figure(figsize=(95,10))
        self.canvas = FigureCanvas(self,-1, self.plt)
        self.toolbar = NavigationToolbar(self.canvas)

        #Hide the Matplotlib toolbar because we are going to create own own
        #but use the functions of this toolbar.
        self.toolbar.Hide()

    def plot(self):
        d = {'BS':[17.54,17.55,17.54,17.53,17.55,17.54],'CAL':[17.46,17.47,17.49,17.44,17.47,17.49]}
        data = pd.DataFrame(d, index=['1','2','3','4','5','6'])

        num_columns = len(data.columns)
        axes_1 = self.plt.add_subplot(1, num_columns, 1)
        #data_numpy = data[data.columns[0]].to_numpy()  # My version of pandas doesn't have .to_numpy()
        data_numpy = data[data.columns[0]]
        #depth = data.index.to_numpy()
        depth = data.index
        self.plt.gca().invert_yaxis()
        self.plt.subplots_adjust(left=0.01, right=0.50, top=0.95, bottom=0.05)
        axes_1.plot(data_numpy, depth)
        for i in range(0, num_columns):
            axes_tmp = self.plt.add_subplot(1, num_columns, i+1, sharey=axes_1)
            axes_tmp.set(xlabel=data.columns[i], ylabel='Depth', title='Depth vs ' + data.columns[i])

            #data_numpy = data[data.columns[i]].to_numpy()
            data_numpy = data[data.columns[i]]

            self.plt.gca().invert_yaxis()
            axes_tmp.plot(data_numpy, depth)
        self.canvas.draw()
        self.SetSize(self.canvas.GetSize())

class TestFrame(wx.Frame):
    def __init__(self,parent,title):
        wx.Frame.__init__(self,parent,title=title,size=(600,600))

        self.p1 = PlotPanel(self)

        #Create our own toolbar
        toolbar = self.CreateToolBar(style=wx.TB_HORIZONTAL|wx.TB_DOCKABLE|wx.TB_TEXT)
        hometool = toolbar.AddTool(wx.ID_ANY, 'Home', wx.Bitmap('/usr/share/matplotlib/mpl-data/images/home.png'))
        backtool = toolbar.AddTool(wx.ID_ANY, 'Back', wx.Bitmap('/usr/share/matplotlib/mpl-data/images/back.png'))
        fwdtool = toolbar.AddTool(wx.ID_ANY, 'Forward', wx.Bitmap('/usr/share/matplotlib/mpl-data/images/forward.png'))
        pantool = toolbar.AddTool(wx.ID_ANY, 'Pan', wx.Bitmap('/usr/share/matplotlib/mpl-data/images/move.png'))
        zoomtool = toolbar.AddTool(wx.ID_ANY, 'Zoom', wx.Bitmap('/usr/share/matplotlib/mpl-data/images/zoom_to_rect.png'))
        subtool = toolbar.AddTool(wx.ID_ANY, 'Subplots', wx.Bitmap('/usr/share/matplotlib/mpl-data/images/subplots.png'))
        savetool = toolbar.AddTool(wx.ID_ANY, 'Save', wx.Bitmap('/usr/share/matplotlib/mpl-data/images/filesave.png'))

        self.Bind(wx.EVT_TOOL, self.home, hometool)
        self.Bind(wx.EVT_TOOL, self.back, backtool)
        self.Bind(wx.EVT_TOOL, self.fwd, fwdtool)
        self.Bind(wx.EVT_TOOL, self.pan, pantool)
        self.Bind(wx.EVT_TOOL, self.zoom, zoomtool)
        self.Bind(wx.EVT_TOOL, self.sub, subtool)
        self.Bind(wx.EVT_TOOL, self.save, savetool)
        toolbar.Realize()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.p1,1,wx.EXPAND,10)
        self.statusbar=self.CreateStatusBar()
        self.SetSizer(sizer)
        self.Show()
        self.plot()

    #Self defined Navigation Toolbar controls used to call hidden matplotlib Toolbar functions
    def home(self,event):
        self.statusbar.SetStatusText("Home")
        self.p1.toolbar.home()
        # Also scroll panel to start position
        self.p1.Scroll(0,0)

    def back(self,event):
        self.statusbar.SetStatusText("Back")
        self.p1.toolbar.back()

    def fwd(self,event):
        self.statusbar.SetStatusText("Fwd")
        self.p1.toolbar.forward()

    def pan(self,event):
        self.statusbar.SetStatusText("Pan")
        self.p1.toolbar.pan()

    def zoom(self,event):
        self.statusbar.SetStatusText("Zoom")
        self.p1.toolbar.zoom()

    def sub(self,event):
        self.statusbar.SetStatusText("Subplots")
        self.p1.toolbar.configure_subplots(event)

    def save(self,event):
        self.statusbar.SetStatusText("Save")
        self.p1.toolbar.save_figure()

    def plot(self):
        self.p1.plot()

app = wx.App(redirect=False)
frame = TestFrame(None,"Plot in Scrolled panel with replacement Navigation")
app.MainLoop()

enter image description here

您会注意到,我将替换项toolbar固定在了Dockable上,因此可以将toolbar移到屏幕上想要的任何位置。它是可重新连接的。

enter image description here

由于我们要定义自己的工具栏,因此它可以在我们想要的任何位置,只需查看wx.Toolbar的选项即可。
在这里,我丢失了文本并将其设置为垂直。

enter image description here