我有一个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()
您会注意到,我使替换
toolbar
可停靠,因此可以将toolbar
移到屏幕上想要的任何位置。它是可重新连接的。因为我们定义了自己的工具栏,所以它可以在我们想要的任何地方,只需查看
wx.Toolbar
的选项。在这里,我丢失了文字并将其垂直放置。
关于python - (wxpython)使matplotlib NavigationToolbar静态化为scrolledpanel中的图形,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55549651/