使用wxPython将NavigationToolbar嵌入到与FigureCanvas不同的框架中

时间:2013-09-27 21:48:10

标签: python python-2.7 matplotlib wxpython

我想将matplotlib.backends.backends_wx.NavigationToolbar2Wx添加到我正在开发的GUI中,但我宁愿不在FigureCanvas上,因为它会强制我的布局相当尴尬。有没有办法将NavigationToolbar2Wx添加到GUI的不同部分而不是它附加到的画布?特别是,我想要以下布局

+------------------------------------------------------------------------+
| +--------------------------------------------------------------------+ |
| |                                                                    | |
| |                                                                    | |
| |                                                                    | |
| |                                                                    | |
| |                            FigureCanvas                            | |
| |                                                                    | |
| |                                                                    | |
| +--------------------------------------------------------------------+ |
| +--------------------------------------------------------------------+ |
| |  TextCtrl   TextCtrl        NavToolbar           TextCtrl  Button  | |
| +--------------------------------------------------------------------+ |
|                                                                        |
|                               More GUI here                            |
|                                                                        |
+------------------------------------------------------------------------+

FigureCanvas及其下方的部分位于同一垂直BoxSizer,而NavigationToolbar的区域为水平BoxSizer

我尝试过各种各样的事情,例如明显构造工具栏,将sizer设置为水平BoxSizer,然后将其添加到BoxSizer,但它不会绘制(尽管InspectionTool将突出显示它应该是, and when I close the window it throws a segfault. If I don't set the sizer for the toolbar, the behavior is identical except it doesn't throw a segfault. I am making sure to call。在工具栏上实现()and。更新()`,但到目前为止,我没有运气。

我想做什么,或者我是否必须手动实施按钮和行为?

1 个答案:

答案 0 :(得分:0)

扩展我的评论,这是一个几乎:-)工作的例子,遗漏了琐碎的部分。我已经使用wx.lib.agw.buttonpanel作为我的工具栏,但粗糙的其他任何东西都可以使用。

import wx.lib.agw.buttonpanel as BP
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx


#---------------------------- plot panel -----------------------------
class PanelWithCanvas(wx.Panel):
    """
    This panel contains plot figure and other things...
    """
    def __init__(self, parent, frame):
        wx.Panel.__init__(self, parent)

        self.frame = frame

        ...

        # create figure
        self.figure = plt.Figure()
        self.axes  = self.figure.add_subplot(111)
        self.axes.grid()
        # attach a canvas to the figure
        self.canvas = FigureCanvas(self, wx.ID_ANY, self.figure) 

        # create the default matplotlib toolbar and attach it to the canvas
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        # realize and hide it, since it will be replaced by a better one
        self.toolbar.Realize()
        self.toolbar.Hide()

        # create a new plot toolbar to replace the default one
        self.ptb = plotToolbar(self)

        ...


#---------------------------- plot toolbar -----------------------------
class plotToolbar(BP.ButtonPanel):
    """
    Create small toolbar which is added to the main panel
    par:  parent
    """
    def __init__(self, par):
        BP.ButtonPanel.__init__(self, par)

        # PanelWithCanvas
        self.pwc = par

        self.ID_FIT = wx.NewId()
        self.ID_ZOOM = wx.NewId()
        self.ID_PAN = wx.NewId()
        self.ID_SAVE = wx.NewId()

        self.AddSpacer()

        btn1 = BP.ButtonInfo(self, self.ID_FIT, bitmaps['zoomfit'].GetBitmap(),
                         shortHelp='Fit plot extents')
        self.AddButton(btn1)
        self.Bind(wx.EVT_BUTTON, self.ZoomFit, btn1)

        self.btnzoom = BP.ButtonInfo(self, self.ID_ZOOM, bitmaps['zoom'].GetBitmap(),
                         kind=wx.ITEM_CHECK, shortHelp='Zoom in/out')
        self.AddButton(self.btnzoom)
        self.Bind(wx.EVT_BUTTON, self.Zoom, self.btnzoom)

        self.btnpan = BP.ButtonInfo(self, self.ID_PAN, bitmaps['pan'].GetBitmap(),
                         kind=wx.ITEM_CHECK, shortHelp='Move plot')
        self.AddButton(self.btnpan)
        self.Bind(wx.EVT_BUTTON, self.Pan, self.btnpan)

        btnsav = BP.ButtonInfo(self, self.ID_SAVE, bitmaps['saveimage'].GetBitmap(),
                         shortHelp='Save image')
        self.AddButton(btnsav)
        self.Bind(wx.EVT_BUTTON, self.SaveImage, btnsav)

        self.AddSpacer()

        self.DoLayout()

    def ZoomFit(self, event):
        self.pwc.toolbar.home()
        event.Skip()

    def Zoom(self, event):
        self.pwc.toolbar.zoom()
        event.Skip()

    def Pan(self, event):
        self.pwc.toolbar.pan()
        event.Skip()

    def SaveImage(self, event):
        self.pwc.toolbar.save_figure(None)
        event.Skip()

请注意,您必须自己管理按钮的行为,因为其中一些只是推送(适合全部,保存),有些是切换(缩放,平移)并且也是相互排斥的......或者您可以将它们全部保留为NavigationToolbar2Wx中的按钮。希望这会有所帮助。