Error attribute zoom panels using wxpython

hi,

i have some Error when i select zoom wirh retangle patch to show it in panel and paneltwo i can see the selection but when i click mouse in panel to mouve it betwen panel and panel two i get error :

File “/home/tm.py”, line 126, in on_press self.GrandParent.panel.three.Update(x1,y1,lon,lat,vis006) AttributeError: ‘NoneType’ object has no attribute ‘panel’ >>>


how can i fix this error ? to show rectangle in panel&paneltwo in the same time

the second problem that i need to showing the value of variable VIS006 for panel and IR2 for paneltwo in the panelthree the same time when i click in rectangle in panel i can get information about panel and paneltwo in panelthree !

thank you

that the example code :

import wx
import numpy as np
import netCDF4
import h5py
from netCDF4 import Dataset
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
import matplotlib
import matplotlib.pyplot as plt
class MainFrame(wx.Frame):
    """ Fenêtre principale de l'application """

    def __init__(self, parent):
        super().__init__(parent,size = (2000,950))
        global x1, y1
self.root = RootPanel(self)
        self.panel=Panel(self)
        self.panel_two=PanelTwo(self)
        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        sizer1.Add(self.root, 1, wx.EXPAND)
        sizer1.Add(self.panel, 1, wx.EXPAND)
        sizer1.Add(self.panel_two, 1, wx.EXPAND)
        self.SetSizer(sizer1)

class RootPanel(wx.Panel):
    """ Panel contenant tous les autres widgets de l'application """

    def __init__(self, parent):
        super().__init__(parent)

        panel_buttons = wx.Panel(self)
        panel_buttons_sizer = wx.GridSizer(1, 2, 0, 0)

        self.canvas_panel = CanvasPanel(self)
        self.panel_three = PanelThree(parent=self)

        select_button = PickButton(
            panel_buttons,
            "netCDF4 files (nc)|*.nc",
            self.canvas_panel.load_from_file,
            label="Show on this window (nc)",
        )
        toplevel_select_button = TopLevelPickButton(
            panel_buttons,
            "Text files (txt)|*.txt|All files|*.*",
            label="Show on separate window (txt)",
        )
        panel_buttons_sizer.Add(select_button)
        panel_buttons_sizer.Add(toplevel_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.panel_three,1,wx.EXPAND)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panel_buttons)
        sizer.Add(canvas_sizer)
        self.SetSizerAndFit(sizer)
        self.Show()

class Panel(wx.Panel):
    def __init__(self,parent):
        super().__init__(parent,size=(200,200))
    def Update(self,parent):
        #Load axis values of the selected rectangle
        zoom_axes=parent.        zoom_axes
self.figure = Figure(figsize =(5,4))
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.axes = self.figure.add_subplot(111)
        self.figure.subplots_adjust(left=0.009,right=0.99,bottom=0.09,top=0.99)
        self.axes.axis(zoom_axes)

        fic='Mmultic3kmNC4_msg04_201905080200.nc'

        path='/data/'
        #path=''
        fic1='/data/latlon_+000.0_globe.nc'

        nc = netCDF4.Dataset(path+fic,'r')
        vis006 = nc.variables['VIS006'][:]
        nc1 = netCDF4.Dataset(fic1,'r')
        lons = nc1.variables['lon'][:]
        lats = nc1.variables['lat'][:]
        self.lons = lons[:]
        self.lats = lats[:]
        self.vis006 = vis006[:]

        self.axes.imshow(self.vis006 ,cmap=plt.cm.gist_yarg)

        self.canvas.mpl_connect('button_press_event', self.on_press)
        x = y = 0.05
        self.rect = patches.Rectangle((x, y), 0.1,0.1,edgecolor='r', alpha=1, fill=None, label='Label')
        self.axes.add_patch(self.rect)
        self.figure.add_axes(self.axes)
        'self.figure.show()'
        self.axes.plot()

    def on_press(self, click):
        x1, y1 = click.xdata, click.

        ydata
#air_dep seems the wrong way round but what do I know
        #The way below gives values that seem correct
        vis006 = self.vis006[int(y1),int(x1)]
        lon = self.lons[int(y1),int(x1)]
        lat = self.lats[int(y1),int(x1)]
        self.GrandParent.panel.three.Update(x1,y1,lon,lat,vis006)
        zx1 = x1 - 0.05
        zy1 = y1 - 0.05
        zx2 = x1 + 0.05
        zy2 = y1 + 0.05
        self.rect.set_x(x1 - 0.05) #Move the rectangle and centre it on the X click point
        self.rect.set_y(y1 - 0.05) #Move the rectangle and centre it on the Y click point

        self.axes.plot()
        self.canvas.draw()
        global zoom
self.zoom_axes=[zx1,zx2,zy1,zy2]
        self.GrandParent.panel.Update(self.zoom_axes)
        'self.GrandParent.panel.two.Update(self.zoom_axes)'

class PanelTwo(wx.Panel):
    def __init__(self,parent):
        super().__init__(parent,name = "PanelTwo",size=(200,200))
    def Update(self,parent):
        zoom_axes=parent.
        zoom_axes
#Load axis values of the selected rectangle
        self.figure = Figure(figsize =(5,4))
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.axes = self.figure.add_subplot(111)
        self.figure.subplots_adjust(left=0.009,right=0.99,bottom=0.09,top=0.99)
        self.axes.axis(zoom_axes)

        fic='Mmultic3kmNC4_msg04_201905080200.nc'

        path='/data/'
        #path=''
        fic1='/data/latlon_+000.0_globe.nc'

        nc = netCDF4.Dataset(path+fic,'r')
        IR2 = nc.variables['IR_108'][:]
        nc1 = netCDF4.Dataset(fic1,'r')
        lons = nc1.variables['lon'][:]
        lats = nc1.variables['lat'][:]

        self.IR2 = IR2[:]
        self.axes.imshow(self.IR2 ,cmap=plt.cm.gist_yarg)

        self.canvas.mpl_connect('button_press_event', self.on_press)
        x = y = 0.05
        self.rect = patches.Rectangle((x, y), 0.1,0.1,edgecolor='r', alpha=1, fill=None, label='Label')
        self.axes.add_patch(self.rect)
        self.figure.add_axes(self.axes)
        self.axes.plot()

    def on_press(self, click):
        global x1,
        y1
x1, y1 = click.xdata, click.

        ydata
#air_dep seems the wrong way round but what do I know
        #The way below gives values that seem correct
        IR2 = self.IR2[int(y1),int(x1)]
        zx1 = x1 - 0.05
        zy1 = y1 - 0.05
        zx2 = x1 + 0.05
        zy2 = y1 + 0.05
        self.rect.set_x(x1 - 0.05) #Move the rectangle and centre it on the X click point
        self.rect.set_y(y1 - 0.05) #Move the rectangle and centre it on the Y click point

        self.axes.plot()
        self.canvas.draw()
        global zoom
self.zoom_axes=[zx1,zx2,zy1,zy2]
        'self.GrandParent.panel.two.Update(self.zoom_axes)'

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

class TopLevelPickButton(PickButton):
    """ Permet de choisir un fichier et d'ouvrir une toplevel """

    def __init__(self, parent, wildcard, **kwargs):
        super().__init__(parent, wildcard, self.create_toplevel, **kwargs)

    def create_toplevel(self, file_name):
        """ Ouvre une toplevel et affiche le graphique """
        self.win = TopLevelCanvas(self.Parent)
        self.win.canvas_panel.load_from_file(file_name)
        self.win.Show()

class CanvasPanel(wx.Panel):
    """ Panel du graphique matplotlib """
    def __init__(self, parent , size=(200,250)):
        super().__init__(parent)
        self.figure = Figure(figsize =(5,5))
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.Size = self.canvas.Size
        self.parent = parent
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_txt(self, file_name):
        self._load_nc(file_name)

    def _load_nc(self, file_name):
        """ Simule le chargement et affichage à partir d'un fichier nc """
        fic='Mmultic3kmNC4_msg04_201905080200.nc'

        path='/data/'
        #path=''
        fic1='/data/latlon_+000.0_globe.nc'

        nc = netCDF4.Dataset(path+fic,'r')
        IR2 = nc.variables['IR_108'][:]
        nc1 = netCDF4.Dataset(fic1,'r')
        lons = nc1.variables['lon'][:]
        lats = nc1.variables['lat'][:]

        self.IR2 = IR2[:]
        self.lons = lons[:]
        self.lats = lats[:]
        self.lonl = len(self.lons) -1
        self.latl = len(self.lats) -1

        self.axes.imshow(self.IR2 ,cmap=plt.cm.gist_yarg)

        self.canvas.mpl_connect('button_press_event', self.on_press)
        x = y = 1
        self.rect = patches.Rectangle((x, y), 5,5,edgecolor='r', alpha=1, fill=None, label='Label')
        self.axes.add_patch(self.rect)
        self.axes.plot()

    def on_press(self, click):
        x1, y1 = click.xdata, click.
        ydata
#air_dep seems the wrong way round but what do I know
        #The way below gives values that seem correct
        IR2 = self.IR2[int(y1),int(x1)]
        IR2_rect = []
        x = int(x1)
        y = int(y1)

        lon = self.lons[int(y1),int(x1)]
        lat = self.lats[int(y1),int(x1)]
        # Build valid values for rectangle
        # to cater for values beyond the edge of the map
        if x-1 < 0: x2 = 0
        else: x2 = x-2
        if x+2 > self.lonl: x3 = self.lonl+1
        else: x3 = x+3
        if y-2 < 0:
            pass
        else:
            IR2_rect.append(self.IR2[y-2,x2:x3])
        if y-1 < 0:
            pass
        else:
            IR2_rect.append(self.IR2[y-1,x2:x3])
        IR2_rect.append(self.IR2[y,x2:x3])
        if y+1 > self.latl:
            pass
        else:
            IR2_rect.append(self.IR2[y+1,x2:x3])
        if y+2 > self.latl:
            pass
        else:
            IR2_rect.append(self.IR2[y+2,x2:x3])

        self.parent.panel_three.Update(x1,y1,IR2,lon,lat,IR2_rect)

        zx1 = x1 - 2.5
        zy1 = y1 - 2.5
        zx2 = x1 + 2.5
        zy2 = y1 + 2.5
        self.rect.set_x(x1 - 2.5) #Move the rectangle and centre it on the X click point
        self.rect.set_y(y1 - 2.5) #Move the rectangle and centre it on the Y click point

        self.axes.plot()
        self.canvas.draw()
        self.zoom_axes=[zx1,zx2,zy1,zy2]

        self.GrandParent.panel.Update(self)
        self.GrandParent.panel_two.Update(self)

class PanelThree(wx.Panel): #here when i need to visualize pixel and coordinator cursor
    def __init__(self,parent):
        wx.Panel.__init__(self,parent,size=(300,350))

        self.text_ctrl = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2, size=(300,300))

        lbl = wx.StaticText(self,label="Coordinato cursor & Pixel ")
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(lbl,0, wx.ALIGN_CENTRE,10)
        sizer.Add(self.text_ctrl,0, wx.ALIGN_CENTRE,10)
        self.SetSizer(sizer)

    def Update(self,x1,y1,IR2,lon,lat,IR2_rect):
        update_str = "Mouse click at;\nX : "+str(int(x1))+"\nY : "+str(int(y1))+" " +"\nIR : "+ str(int(IR2 - 273.15))+" "+"\nLon : "+str(int(lon))+"\nLat :"+str(int(lat))
        self.text_ctrl.SetValue(update_str)
        self.text_ctrl.write("\nIR2")
        #Table of surrounding temperatures
        for i in range(len(IR2_rect)):
            s = ""
            line = IR2_rect[i]
            for i2 in line:
                s+="{:5.1f}".format(i2-273.15)+" "
            self.text_ctrl.write(s+"\n")

app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()

···

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/14b84640-9a17-458b-bce9-3718a00217ad%40googlegroups.com.

Again, this is an organizational problem. Perhaps you need to use a
separate class to store your shared data, and pass that “state”
object to the various panels. This is basically a “model/view”
pattern, where you have one class that just holds the information
you are working with, and “view” classes that actually display the
user interface to manage that data. All of the references to Parent
and GrandParent are signs of a flawed design that is too deeply
interconnected. With rare exceptions, a single panel should not be
working with data or controls on another panel. They should be
making requests through some common ancestor object.
– You received this message because you are subscribed to the Google Groups “wxPython-users” group.
To unsubscribe from this group and stop receiving emails from it, send an email to .
To view this discussion on the web visit .

···

Maj wrote:

hi,

      i have some Error when i select zoom wirh retangle patch to

show it in panel and paneltwo i can see the selection but when
i click mouse in panel to mouve it betwen panel and panel two
i get error :

File “/home/tm.py”, line 126, in on_press self.GrandParent.panel.three.Update(x1,y1,lon,lat,vis006) AttributeError: ‘NoneType’ object has no attribute ‘panel’ >>>



how can i fix this error ? to show rectangle in panel&paneltwo in the same time


  I'm curious to know what you were expecting.  The parent of Panel

is MainFrame. The parent of MainFrame, as you created it in the
next to the last line, is None. Thus, in Panel.on_press,
self.GrandParent will always be None, just as the error says.

  Did you intend that Panel be a child of RootPanel?  If so, you

need to say so, in MainFrame.init:

self.root = RootPanel( self )
self.panel = Panel( self.root )

Even after you do that, however, this code still has problems:

self.GrandParent.panel.three.Update( … )

  Let's say you do update the initialization so Panel is a child of

RootPanel, which is in turn a child of MainFrame. In that case,
MainFrame.panel is just the Panel instance, so that line would be
exactly the same as saying:

self.three.Update( … )

  But there is no "three" defined in any of the panels.  Was that a

typo? Did you mean to say panel_three instead of panel.three?
panel_three is a member of RootPanel. So, after you make the
change above to have Panel be a child of RootPanel, you would want
to use Parent, not GrandParent:

self.Parent.panel_three.Update( … )

  It might be worthwhile for you to draw out a diagram of the

parent/child relationships, just to make sure you get the
references right.

the second problem that i need to showing the value of variable VIS006 for panel and IR2 for paneltwo in the panelthree the same time when i click in rectangle in panel i can get information about panel and paneltwo in panelthree !


-- Tim Roberts, Providenza & Boekelheide, Inc.

wxpython-users+unsubscribe@googlegroups.com
https://groups.google.com/d/msgid/wxpython-users/ddb26cec-328c-3273-0bec-1523e73da03f%40probo.com
timr@probo.com

First, please try to reduce your samples to as little as possible that is runnable and will demonstrate your problem, and that does not require external data files, or etc.

Second, deeply probing up the containment hierarchy, like self.GrandParent.panel.three.Update(...) is a really fragile design, and, as you’ve discovered, very prone to breakage. (For the record, deeply probing down the hierarchy can sometimes be troublesome too, but not as often as going up.) There are many techniques for reducing the coupling between components in your application, all the way up to standard patterns like MVC or MVP. The main approach in cases like this would be to eliminate the need for one component to direct knowledge about the structure of other components above it. IOW, it should not know, nor care about its parents, grandparents, siblings, cousins or any other entity other than itself, and perhaps its own children.

If you aren’t able to redesign the application to do away with this sort of crosstalk between components, then you may want to consider replacing direct method calls like that with a message passing package, like pypubsub. So instead of making a obj0.obj1.obj2.obj3.method() kind of call, you just send a message and continue on with whatever you need to do next. It is then the responsibility of the target of that message to be listening for it and then do whatever it needs to do in response to that message.

···

Robin

Discuss wxPython

On Thursday, July 25, 2019 at 11:53:33 AM UTC-7, Maj wrote:

hi,

i have some Error when i select zoom wirh retangle patch to show it in panel and paneltwo i can see the selection but when i click mouse in panel to mouve it betwen panel and panel two i get error :

File “/home/tm.py”, line 126, in on_press self.GrandParent.panel.three.Update(x1,y1,lon,lat,vis006) AttributeError: ‘NoneType’ object has no attribute ‘panel’ >>>





You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/3a031462-140f-463e-9638-cc861045a6bd%40googlegroups.com.