Search code examples
pythonwxpythonseaborn

Seaborn disable plot


I have a seaborn barplot embedded in a WxPython panel, like this:

enter image description here

The bar plot is drawn when the (big) button is clicked. This is what I made to accomplish it:

class SamplePanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.figure = Figure()
        self.ax = self.figure.add_subplot(111)

        self.x = np.array(list('XYZV'))
        self.y = np.array([200,400,300,20])

        self.ax.set_ylabel("Sample numbers")        

        self.canvas = FigureCanvas(self, -1, self.figure)
        self.button = wx.Button(self, label="Plot data", pos=(100,15))
        self.button.Bind(wx.EVT_BUTTON, self.OnButtonClick)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.sizer.Add(self.button, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()

    def OnButtonClick(self,event):
        sns.barplot(self.x, self.y, palette="BuGn_d", ax=self.ax)


if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = wx.Frame(None, title='Sample bar plot')
    panel = SamplePanel(frame)
    frame.Show()
    app.MainLoop()

I have two questions:

  • How can I disable/draw the plot when I click the button? That is, if I click the button then the plot appears. If I click again the plot disappears and I get back to an empty original view, like this: enter image description here

    • Also, the plot only changes when I maximize the window, how can I change it to be immediate, as soon as I click the button?

Any suggestions? Thanks in advance


Solution

  • It would have helped a lot if you had posted a small runnable example. Fortunately, Google helped me figure out what all was needed. Basically you need to set some kind of variable to keep track of if you've clicked the button or not. Or you could use a wx.ToggleButton instead of a regular wx.Button.

    To get the graph to display without resizing the frame, you just need to call self.Layout().

    To clear the figure, you'll need to do something like self.ax.cla() or self.ax.clear(). Here's a full example that worked for me:

    import numpy as np
    import seaborn as sns
    import wx
    
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
    from matplotlib.figure import Figure
    
    class SamplePanel(wx.Panel):
        def __init__(self, parent):
            wx.Panel.__init__(self, parent)
            self.toggled = False
            self.figure = Figure()
            self.ax = self.figure.add_subplot(111)
    
            self.x = np.array(list('XYZV'))
            self.y = np.array([200,400,300,20])
    
            self.ax.set_ylabel("Sample numbers")
    
            self.canvas = FigureCanvas(self, -1, self.figure)
            self.button = wx.Button(self, label="Plot data", pos=(100,15))
            self.button.Bind(wx.EVT_BUTTON, self.OnButtonClick)
    
            self.sizer = wx.BoxSizer(wx.VERTICAL)
            self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
            self.sizer.Add(self.button, 1, wx.LEFT | wx.TOP | wx.GROW)
            self.SetSizer(self.sizer)
            self.Fit()
    
        def OnButtonClick(self, event):
            if not self.toggled:
                sns.barplot(self.x, self.y, palette="BuGn_d", ax=self.ax)
                self.toggled = True
            else:
                self.ax.cla()
                self.toggled = False
            self.Layout()
    
    
    if __name__ == "__main__":
        app = wx.App(False)
        frame = wx.Frame(None, title='Sample bar plot', size=(800,600))
        panel = SamplePanel(frame)
        frame.Show()
        app.MainLoop()
    

    Also note that wx.PySimpleApp is deprecated. I swapped it out for the recommended method of creating an app object.