我有一个Matplotlib图,其中包含很多需要ScrolledPanel的子图。现在,我想为该图添加一个navigation toolbar,使其在滚动图panel时保持静态。
我尝试将其添加到画布父级之外的其他面板中,但这不起作用(导航工具栏仅保留在画布父级中)。
有什么方法可以使matplotlib导航工具栏保持静态,但使其余画布可滚动?
这是我完整的代码:

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这是一个熊猫数据框
样本数据:

| index | BS   | CAL  |
|-------|------|------|
| 162   | 17.5 | 17.4 |
| 163   | 17.8 | 17.7 |
| 164   | 17.8 | 17.9 |

最佳答案

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

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


python - (wxpython)使matplotlib NavigationToolbar静态化为scrolledpanel中的图形-LMLPHP

您会注意到,我使替换toolbar可停靠,因此可以将toolbar移到屏幕上想要的任何位置。它是可重新连接的。

python - (wxpython)使matplotlib NavigationToolbar静态化为scrolledpanel中的图形-LMLPHP

因为我们定义了自己的工具栏,所以它可以在我们想要的任何地方,只需查看wx.Toolbar的选项。
在这里,我丢失了文字并将其垂直放置。

python - (wxpython)使matplotlib NavigationToolbar静态化为scrolledpanel中的图形-LMLPHP

关于python - (wxpython)使matplotlib NavigationToolbar静态化为scrolledpanel中的图形,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55549651/

10-12 18:33