简体   繁体   中英

matplotlib graph embedded in wxPython panel does not display entire graph

My goal is to have multiple relatively small graphs being generated in the same wxPython panel. Additionally, I would like to manually resize the graphs and place them where I want. This causes issues because my graphs are displayed incorrectly. Changing the size of the graph does not change the graph itself, it only cuts off parts of the graph. It's easier to see what I mean if you run my code. As you can see, the graph on the right is fully displayed, but it is too big and I want to make it a bit smaller. However, the smaller graph on the left is missing half of the graph! Does anyone have an idea as to how this can be fixed?

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

I have found another thread with a similar problem, but the thread's solution did not work correctly and the graphs were still displayed incorrectly.

I respectfully disagree with the earlier answer. The problem is not that a sizer should be included in your Graph() . Using sizers instead of fixed positions is definitely a good idea, but not the cause of the problem here.

The problem you are seeing is that the default size of the the matplotlib Figure is larger than your smaller graph. To fix this, you should specify the figure size, and the dpi for the figure. One way to do that is to use the size given to Graph.__init__() to set the size of the Figure . For example:

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

which will scale both Graph() s appropriately.

I would definitely suggest not using absolute position, but rather using sizers, for example

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)

Finally, allow me to also suggest using wxmplot ( https://newville.github.io/wxmplot/ ), which has a PlotPanel class that puts a matplotlib plot on a wxPython Panel , for example:

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM