嵌入在wxPython面板中的matplotlib图不会显示整个图



我的目标是在同一个wxPython面板中生成多个相对较小的图形。此外,我想手动调整图表的大小并将它们放置在我想要的位置。这会导致问题,因为我的图表显示不正确。改变图形的大小不会改变图形本身,它只会切断图形的一部分。如果你运行我的代码,更容易理解我的意思。如您所见,右侧的图表已完全显示,但它太大了,我想让它小一点。但是,左侧较小的图形缺少图形的一半!有没有人知道如何解决这个问题?

    import wx
    import matplotlib as mpl
    mpl.use('WXAgg')
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
    from matplotlib.backends.backend_wx import NavigationToolbar2Wx
    from matplotlib.figure import Figure
    class MainFrame(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__(self, None, size=(1200,900))
            self.panel_1 = Panel_one(self)
    class Panel_one(wx.Panel):
        def __init__(self, parent):
            wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
            self.temp_graph = Graph(self, position=(50, 100), size=(400,400))
            self.temp_graph = Graph(self, position=(550, 100), size=(700, 700))
    class Graph(wx.Panel):
        def __init__(self, parent, position, size):
            wx.Panel.__init__(self, parent, pos=position, size=size)
            self.figure = Figure(None)
            self.canvas = Canvas(self, -1, self.figure)
            self.axes = self.figure.add_subplot(111)

    if __name__ == "__main__":
        app = wx.App(redirect=False)
        frame = MainFrame(None)
        frame.Show()
        app.MainLoop()

我发现了另一个具有类似问题的线程,但是该线程的解决方案无法正常工作,并且图形仍然显示不正确。

恭敬地不同意前面的回答。问题不在于您的Graph()中应该包含尺寸器。 使用尺寸器而不是固定位置绝对是一个好主意,但不是这里问题的原因。

您看到的问题是 matplotlib Figure的默认大小大于较小的图形。 要解决此问题,您应该指定图形大小和图形的 dpi。 一种方法是使用给定Graph.__init__()的大小来设置Figure的大小。 例如:

import wx
import matplotlib
matplotlib.use('WXAgg')

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
class MainFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, None, size=(1200, 900))
        self.panel_1 = Panel_one(self)
class Panel_one(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
        self.graph1 = Graph(self, position=(50, 100), size=(400, 400))
        self.graph2 = Graph(self, position=(500, 100), size=(700, 700))

class Graph(wx.Panel):
    def __init__(self, parent,  position, size, dpi=150):
        wx.Panel.__init__(self, parent, pos=position, size=size)
        # Note: here, set the figure size based on size of Graph 
        figsize = (size[0]*1.0/dpi, size[1]*1.0/dpi)
        self.figure = Figure(figsize, dpi=dpi)
        self.canvas = Canvas(self, -1, self.figure)
        self.axes = self.figure.add_subplot(111)

if __name__ == "__main__":
    app = wx.App(redirect=False)
    frame = MainFrame(None)
    frame.Show()
    app.MainLoop()

这将适当地缩放Graph()

例如,我绝对建议不要使用绝对位置,而是使用尺寸器。

class Panel_one(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
        self.graph1 = Graph(self, size=(400, 400))
        self.graph2 = Graph(self, size=(700, 700))
        # Note: here create a sizer and add your graphs to it
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.graph1, 0, wx.LEFT, 5)
        sizer.Add(self.graph2, 0, wx.LEFT, 5)
        self.SetSizer(sizer)

class Graph(wx.Panel):
    def __init__(self, parent,  size, dpi=150):
        wx.Panel.__init__(self, parent, size=size)
        fsize = (size[0]*1.0/dpi, size[1]*1.0/dpi)
        self.figure = Figure(fsize, dpi=dpi)
        self.canvas = Canvas(self, -1, self.figure)
        self.axes = self.figure.add_subplot(111)

最后,请允许我也建议使用 wxmplot (https://newville.github.io/wxmplot/(,它有一个PlotPanel类,可以将 matplotlib 图放在 wxPython Panel 上,例如:

from wxmplot import PlotPanel
class Panel_one(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
        # Note: here use wxmplot.PlotPanel instead of your Graph class
        self.graph1 = PlotPanel(self, size=(400, 400))
        self.graph2 = PlotPanel(self, size=(700, 700))
        sizer = wx.BoxSizer(wx.HORIZONTAL) 
        sizer.Add(self.graph1, 0, wx.LEFT, 5)
        sizer.Add(self.graph2, 0, wx.LEFT, 5)
        self.SetSizer(sizer)