Search code examples
python-3.xmatplotlibwxpython

wxpython can't choose the good panel for zoom


I have this app in wxpython when I select the panel when I need to plot zoom the wxpython can't plot in the correct panel the plot up in the same panel


Solution

  • Where to start?
    In LeftPanelBottom you have defined

    canvas_panel = LeftPanelTop(self)
    self.canvas_panel = LeftPanelTop(self)
    self.zoom_panel = MiddlePanelTop(parent=self)
    

    So that is 2 canvas panels, followed by sizer confusion and the fact that you placed MiddlePanelTop slap bang inside of LeftPanelBottom along with LeftPanelTop which has already been loaded into LeftPanel.

    But the main issue is about inheritance. Because just about everything is defined as a class in its own right, even buttons, trying to find a path through to the MiddlePanelTop escapes me. Perhaps someone else can chime in here, as I got lost.
    The simple and apparently un-pythonic way is to just use a global variable.
    Below, I use a global called Zoom.
    N.B. I have also changed the path to the file, where appropriate

    Edit: I have de-coded your classes within classes and added in the appropriate self entries, which allows us to access them.
    As a result the Left panel now functions as I suppose you intended as well.
    I note that the Right and MiddlePanelBottom panels still have inconsistencies, missing items and fixed positioning.

    import wx
    import numpy as np
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
    from matplotlib.figure import Figure
    from matplotlib.widgets import RectangleSelector
    import matplotlib
    import matplotlib.pyplot as plt
    import os
    import netCDF4
    from netCDF4 import Dataset
    #Zoom = None
    
    
    class MainFrame(wx.Frame):
        def __init__(self, parent ):
            super().__init__(parent,title= "quick",name="Main", size = (2000,1000))
    
            self.left = LeftPanel(self)
            self.middle = MiddlePanel(self)
            self.right = RightPanel(self)
            sizer = wx.BoxSizer(wx.HORIZONTAL)
            sizer.Add(self.left, 1, wx.EXPAND)
            sizer.Add(self.middle, 1, wx.EXPAND)
            sizer.Add(self.right, 1, wx.EXPAND)
            self.SetSizer(sizer)
    
    
    # ------------ LEFT ------------
    class LeftPanel(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent, name="Left", style = wx.SUNKEN_BORDER)
            self.top = LeftPanelTop(self)
            self.bottom = LeftPanelBottom(self)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.top, 1, wx.EXPAND)
            sizer.Add(self.bottom, 1, wx.EXPAND)
    
            self.SetSizer(sizer)
    
    class LeftPanelTop(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent, name="LeftTop", size = (510,350))
            self.figure = Figure(figsize =(5,3))
            self.canvas = FigureCanvas(self, -1, self.figure)
            self.Size = self.canvas.Size
    
        def load_from_file(self, file_name):
            """
            Méthode effectuant l'intermédiaire pour charger le fichier selon
            son type
            """
            self.axes = self.figure.add_subplot(111)
    
            if file_name.endswith(".nc"):
                self._load_nc(file_name)
            else:
                self._load_txt(file_name)
            self.canvas.draw()
    
        def _load_nc(self, file_name):
            """ Simule le chargement et affichage à partir d'un fichier nc """
            path='D:/stage2019/air.departure.sig995.2012.nc'
    
    
            nc = Dataset('./air.departure.sig995.2012.nc')
            lons = nc.variables['lon'][:]
            lats = nc.variables['lat'][:]
            air_dep = nc.variables['air_dep'][:,:,:]
            air_dep = air_dep[0,:,:]
    
            self.axes.pcolormesh(air_dep)
    
    
            self.RS = RectangleSelector(self.axes,self.line_select_callback,
                                           drawtype='box', useblit=False,
                                           button=[1, 3],minspanx=5, minspany=5,
                                           spancoords='pixels',
                                           interactive=True, rectprops = dict(facecolor='None',edgecolor='red',alpha=5,fill=False))
    
    
        def line_select_callback(self, eclick, erelease):
            'eclick and erelease are the press and release events'
            x1, y1 = eclick.xdata, eclick.ydata
            x2, y2 = erelease.xdata, erelease.ydata
            self.zoom_axes=[x1,x2,y1,y2]
    
        # Zoom is a global variable set in MiddlePanelTop __init__
            #Zoom.Update(self.zoom_axes)
            self.GrandParent.middle.top.Update(self.zoom_axes)
    
    
    
    class LeftPanelBottom(wx.Panel):
         def __init__(self, parent):
            super().__init__(parent, name="LeftBottom", style = wx.SUNKEN_BORDER,size = (510,350) )
            self.SetBackgroundColour('snow2')
            panel_buttons = wx.Panel(self)
            panel_buttons_sizer = wx.GridSizer(1, 2, 0, 0)
    
            self.canvas_panel = wx.Panel()
            #self.canvas_panel = LeftPanelTop(self)
            #self.zoom_panel = MiddlePanelTop(parent=self)
            select_button = PickButton(
                panel_buttons,
                "netCDF4 files (nc)|*.nc",
                #self.canvas_panel.load_from_file,
                self.Parent.top.load_from_file,
                label="Open file",)
            panel_buttons_sizer.Add(select_button)
            panel_buttons.SetSizer(panel_buttons_sizer)
            canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
            canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
            #canvas_sizer.Add(self.zoom_panel,1,wx.EXPAND)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(panel_buttons)
            sizer.Add(self.canvas_panel)
            self.SetSizer(sizer)
            self.Show()
    
    
    class PickButton(wx.Button):
        """ Bouton permettant de choisir un fichier """
    
        def __init__(self, parent, wildcard, func, **kwargs):
            # func est la méthode à laquelle devra être foruni le fichier sélectionné
            super().__init__(parent, **kwargs)
            self.wildcard = wildcard
            self.func = func
            self.Bind(wx.EVT_BUTTON, self.pick_file)
    
        def pick_file(self, evt):
            style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
            with wx.FileDialog(
                self, "Pick files", wildcard=self.wildcard, style=style
            ) as fileDialog:
                if fileDialog.ShowModal() != wx.ID_CANCEL:
                    chosen_file = fileDialog.GetPath()
                    self.func(chosen_file)
    
    # ------------ MIDDLE ------------
    class MiddlePanel(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent, name="Middle")
            self.top = MiddlePanelTop(self)
            self.bottom = MiddlePanelBottom(self)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.top, 1, wx.EXPAND, 5)
            sizer.Add(self.bottom, 1, wx.EXPAND, 5)
            self.SetSizer(sizer)
    
    class MiddlePanelTop(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent, name="MiddleTop", style = wx.SUNKEN_BORDER,size = (300,200))
    
        def Update(self,zoom_axes):
            #Load axis values of the selected rectangle
            #zoom_axes=parent.zoom_axes
    
            #duplicate the plot from the main panel
            self.figure = Figure(figsize =(5,3))
            self.canvas = FigureCanvas(self, -1, self.figure)
            self.axes = self.figure.add_subplot(111)
    
            #Apply axis of drawn rectangle to the plot
            self.axes.axis(zoom_axes)
    
            path='./air.departure.sig995.2012.nc'
    
    
            nc = Dataset('./air.departure.sig995.2012.nc')
            lons = nc.variables['lon'][:]
            lats = nc.variables['lat'][:]
            air_dep = nc.variables['air_dep'][:,:,:]
            air_dep = air_dep[0,:,:]
    
            self.axes.pcolormesh(air_dep)
            self.canvas.draw()
            self.Refresh()
    
    
    
    class MiddlePanelBottom(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent, name="MiddleBottom", style = wx.SUNKEN_BORDER)
            self.SetBackgroundColour('black')
            canal=wx.Button(self,-1,"Variable",size=(140,30),pos=(100,0))
            dynamique=wx.Button(self,-1,"Dynamique",size=(140,30),pos=(240,0))
            file = wx.Button(self,-1,"File", size = (110,30),pos=(0,0))
            dynamique.SetBackgroundColour('white')
            canal.SetBackgroundColour('white')
            file.SetBackgroundColour('white')
            dynamique.Bind(wx.EVT_BUTTON, self.OnClick)
            file.Bind(wx.EVT_BUTTON, self.onOpen)
            self.load_options = "netCDF4 files (nc)|*.nc| Text files (txt) |*.txt| All files |*.*"
    
        def onOpen(self, event):
            wildcard = "netCDF4 files (*.nc)|*.nc"
            dialog = wx.FileDialog(self, "Open netCDF4 Files", wildcard=wildcard,
                                   style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
    
            if dialog.ShowModal() == wx.ID_CANCEL:
                return
            path = dialog.GetPath()
    
            if os.path.exists(path):
                with open(path) as fobj:
                    for line in fobj:
                        self.my_text.WriteText(line)
    
        def OnClick(self,event):
            dlg = wx.TextEntryDialog(self, 'Enter Dynamique of image','Dynamique de image')
    
            if dlg.ShowModal() == wx.ID_OK:
             self.text.SetValue("Dynamique:"+dlg.GetValue())
            dlg.Destroy()
    
    
    
    # ------------ RIGHT ------------
    
    class RightPanelTop(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent)
            self.SetBackgroundColour('black')
            canal=wx.Button(self,-1,"Variable",size=(140,30),pos=(100,0))
            dynamique=wx.Button(self,-1,"Dynamique",size=(140,30),pos=(240,0))
            file = wx.Button(self,-1,"File", size = (110,30),pos=(0,0))
            dynamique.SetBackgroundColour('white')
            canal.SetBackgroundColour('white')
            file.SetBackgroundColour('white')
            dynamique.Bind(wx.EVT_BUTTON, self.OnClick)
            file.Bind(wx.EVT_BUTTON, self.onOpen)
    
        def onOpen(self, event):
            wildcard = "netCDF4 files (*.nc)|*.nc| HDF5 files (*.h5) |*.h5"
            dialog = wx.FileDialog(self, "Open netCDF4 Files| HDF5 files", wildcard=wildcard,
                                   style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
    
            if dialog.ShowModal() == wx.ID_CANCEL:
                return
    
            path = dialog.GetPath()
    
            if os.path.exists(path):
                with open(path) as fobj:
                    for line in fobj:
                        self.my_text.WriteText(line)
    
        def OnClick(self,event):
            dlg = wx.TextEntryDialog(self, 'Enter Dynamique of image','Dynamique de image')
    
            if dlg.ShowModal() == wx.ID_OK:
             self.text.SetValue("Dynamique:"+dlg.GetValue())
            dlg.Destroy()
    
    class RightPanel(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent,style = wx.SUNKEN_BORDER)
    
            top = RightPanelTop(self)
            bottom = RightPanelBottom(self)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(top, 1, wx.EXPAND)
            sizer.Add(bottom, 1, wx.EXPAND)
            self.SetSizer(sizer)
    
    class PanelBottom(wx.Panel):
        def __init__(self,parent):
            super().__init__(parent)
            self.SetBackgroundColour('grey77')
    
    class PanelTop(wx.Panel):
        def __init__(self,parent):
            super().__init__(parent)
            left = SubPanelLeft(self)
            right = SubPanelRight(self)
            midlle = SubPanelMiddle(self)
            sizer1 = wx.BoxSizer(wx.HORIZONTAL)
            sizer1.Add(left, 1, wx.EXPAND)
            sizer1.Add(midlle, 1, wx.EXPAND)
            sizer1.Add(right, 1, wx.EXPAND)
    
            self.SetSizer(sizer1)
    
    class RightPanelBottom(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent)
            self.SetBackgroundColour('snow2')
    
            top = PanelTop(self)
            bottom = PanelBottom(self)
            sizer1 = wx.BoxSizer(wx.VERTICAL)
            sizer1.Add(top, 1, wx.EXPAND)
            sizer1.Add(bottom, 1, wx.EXPAND)
            self.SetSizer(sizer1)
    
    
    class SubPanelLeft(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent,style = wx.SUNKEN_BORDER)
            self.SetBackgroundColour('black')
    
    class SubPanelMiddle(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent,style = wx.SUNKEN_BORDER)
            self.SetBackgroundColour('black')
    
    class SubPanelRight(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent,style = wx.SUNKEN_BORDER)
            self.SetBackgroundColour('black')
    
    
    
    
    app = wx.App()
    frame = MainFrame(None).Show()
    app.MainLoop()
    

    enter image description here