Classe per sostituire aree dello schermo

di il
4 risposte

Classe per sostituire aree dello schermo

Ciao!
Voglio creare una classe con due parametri: la vecchia area & la nuova area.
Istruzione: distruggi la vecchia area e sostituiscila con la nuova.

Cosa sbaglio nel ragionamento?

AttributeError: '_tkinter.tkapp' object has no attribute 'switch'

Windows 10, Python 3.9
import tkinter as tk

class Switch():
    def __init__(self, old_top, new_top):
        self.old_top=old_top
        self.new_top=new_top
    def switch(self):
        self.old_top.destroy()
        self.new_top=self.new_top(root)

class Calendario():    
    def __init__(self, master):

        frameTop=tk.Frame(master, bg='red')
        frameTop.grid(row=1, column=0, sticky="wens")
        frameTop.grid_propagate()

        self.bottone=tk.Button(frameTop, bg='white', relief="flat")
        self.bottone.grid(row=0, column=0)
    
        self.label=tk.Label(frameTop, text='Calendario!', font=('MV Boli', 16), bg='white')
        self.label.grid(row=0, column=1, padx=35)

class Top():    
    def __init__(self, master):

        frameTop=tk.Frame(master, bg='violet')
        frameTop.grid(row=0, column=0, sticky="wens")
        frameTop.grid_propagate()

        self.bottone=tk.Button(frameTop, bg='white', relief="flat", command=lambda: master.switch(Top2 ,Calendario))
        self.bottone.grid(row=0, column=0)
    
        self.label=tk.Label(frameTop, text='Hello!', font=('MV Boli', 16), bg='white')
        self.label.grid(row=0, column=1, padx=35)


class Top2():
    def __init__(self, master):

        frameTop=tk.Frame(master, bg='yellow')
        frameTop.grid(row=1, column=0, sticky="wens")
        frameTop.grid_propagate()

        self.bottone=tk.Button(frameTop, bg='white', relief="flat")
        self.bottone.grid(row=0, column=0)
       
        self.label=tk.Label(frameTop, text='Hello!', font=('MV Boli', 16), bg='white')
        self.label.grid(row=0, column=1, padx=35)

class Top3():
    def __init__(self, master):

        frameTop=tk.Frame(master, bg='pink')
        frameTop.grid(row=2, column=0, sticky="wens")
        frameTop.grid_propagate()

        self.bottone=tk.Button(frameTop, bg='white', relief="flat")
        self.bottone.grid(row=0, column=0)
        
        self.label=tk.Label(frameTop, text='Hello!', font=('MV Boli', 16), bg='white')
        self.label.grid(row=0, column=1, padx=35)

root=tk.Tk()
root.title('Hi!')
root.configure(bg='white')
Top1=Top(root)
Top2=Top2(root)
Top3=Top3(root)
root.mainloop()

4 Risposte

  • Re: Classe per sostituire aree dello schermo

    Ciao,
    l'errore ti suggerisce appunto che stai sbagliando a chiamare i metodi. "master" non ha il metodo "switch";
    per risolvere questo ti basterebbe create un oggetto "Switch" a cui passi le due finestre e potresti far richiamare il metodo "switch" dell'oggetto creato dal bottone.

    PS: risolto questo problema dovresti (teoricamente) riscontrare altri errori, se dovessi avere difficoltà a risolverli scrivi pure.
    Buon lavoro.
  • Re: Classe per sostituire aree dello schermo

    Ciao e grazie per la risposta. Ho provato a seguire le tue indicazioni. Ho fatto bene?
    Successivamente, come da previsione, si è creato un nuovo errore che ho tentato di risolvere ...generando così un ulteriore nuovo errore... Ti mostro l'ultimo codice.
    
    import tkinter as tk
    
    class Switch():
        def __init__(self, old_top, new_top):
            self.old_top=old_top
            self.new_top=new_top
        def switch(self):
            self.old_top.destroy()
            self.new_top=self.new_top(root)
    
    self.interruttore_switch_calendario=Switch(self.frameTop2, self.frameTop_calendario) 
    
    
    class Calendario():    
        def __init__(self, master):
    
            self.frameTop_calendario=tk.Frame(master, bg='red')
            self.frameTop_calendario.grid(row=1, column=0, sticky="wens")
            self.frameTop_calendario.grid_propagate()
    
            self.bottone=tk.Button(self.frameTop_calendario, bg='white', relief="flat")
            self.bottone.grid(row=0, column=0)
        
            self.label=tk.Label(self.frameTop_calendario, text='Calendario!', font=('MV Boli', 16), bg='white')
            self.label.grid(row=0, column=1, padx=35)
    
    class Top():    
        def __init__(self, master):
    
            self.frameTop=tk.Frame(master, bg='violet')
            self.frameTop.grid(row=0, column=0, sticky="wens")
            self.frameTop.grid_propagate()
    
            self.bottone=tk.Button(self.frameTop, bg='white', relief="flat", command=self.switch)
            self.bottone.grid(row=0, column=0)
        
            self.label=tk.Label(self.frameTop, text='Hello!', font=('MV Boli', 16), bg='white')
            self.label.grid(row=0, column=1, padx=35)
    
    
    class Top2():
        def __init__(self, master):
    
            self.frameTop2=tk.Frame(master, bg='yellow')
            self.frameTop2.grid(row=1, column=0, sticky="wens")
            self.frameTop2.grid_propagate()
    
            self.bottone=tk.Button(self.frameTop2, bg='white', relief="flat")
            self.bottone.grid(row=0, column=0)
           
            self.label=tk.Label(self.frameTop2, text='Hello!', font=('MV Boli', 16), bg='white')
            self.label.grid(row=0, column=1, padx=35)
    
    class Top3():
        def __init__(self, master):
    
            self.frameTop3=tk.Frame(master, bg='pink')
            self.frameTop3.grid(row=2, column=0, sticky="wens")
            self.frameTop3.grid_propagate()
    
            self.bottone=tk.Button(self.frameTop3, bg='white', relief="flat")
            self.bottone.grid(row=0, column=0)
            
            self.label=tk.Label(self.frameTop3, text='Hello!', font=('MV Boli', 16), bg='white')
            self.label.grid(row=0, column=1, padx=35)
    
    
    root=tk.Tk()
    root.title('Hi!')
    root.configure(bg='white')
    Top1=Top(root)
    Top2=Top2(root)
    Top3=Top3(root)
    root.mainloop()
    
    Già che ci siamo, mi diresti cortesemente se questo schema è corretto? Vorrei confrontarmi sulla teoria.
    
    class Dog:                  # def classe (fabbrica con modello)
        def __init__(self, name):   
            self.name=name       # crea attributo istanza [attivazione attributi]
    
        def print_name(self): # def metodo (istruzione) <-- accede all'attributo istanza
            print(self.name)
    
    dog=Dog('Rex')  # crea istanza (oggetto che segue il modello)
    
    dog.name   # accede all'attributo istanza & chiama valore -->'Rex'
    
    dog.print_name()   # chiama istruzione & la applica all'istanza
                       # il "self" è riportato in automatico, si può omettere
                       # [stamperà --> Rex]
    
    dog.name='Gigi'   # accede all'attributo istanza e cambiare valore:
                      # DICHIARARE ATTRIBUTI DI CLASSE
    # oppure "attributo=valore"
                    
    dog.name          # chiama valore
    
    dog.print_name()   # stampa valore      [perché è istruzione fabbrica]
    
    
    '''
    ATTRIBUTI:
    
    "istanza"   <--- accessibili solo all'istanza
                <--- definito da __init--
                
    "classe"    <--- accessibili da classe e sue istanze
                <--- dichiarato durante definizione classe
    '''
    
    class Dog:
        scientific_name='Canis lupus familiaris'   # attributo classe definito
    
        def __init__(self, name):
            self.name=name                         # attributo istanza dichiarato
    
        def print_name(self): # def metodo (istruzione) <-- accede all'attributo istanza
            print(self.name)
    
    rex = Dog('Rex')   
    fido = Dog('Fido')                               # create due istanze
    
    rex.name                   # chiamare valori istanze   -->'Rex', 'Fido'
    fido.name
    
    Dog.scientific_name        # chiamare valore classe da classe
                               #  --->'Canis lupus familiaris'
                               # [si è acceduto agli ATTRIBUTI di ISTANZA & CLASSE
    
    rex.scientific_name        # chiamare valore classe da istanze
    fido.scientific_name
    
    rex.print_name()                 
    
  • Re: Classe per sostituire aree dello schermo

    Ciao,
    Hai fatto qualche modifica, ma non del tutto esatta;

    Un consiglio molto importante: presta molta attenzione alle maiuscole e minuscole, le variabili e gli oggetti andrebbero scritti con l'iniziale minuscole, mentre, le classi andrebbero con l'iniziale maiuscola; (mi riferisco agli oggetti Top1, Top2 e Top3, che rischiano di andare in conflitto avendo lo stesso nome della classe (sia maiuscole che minuscole))

    Ho guardato il secondo codice che hai mandato, e mi sembra tutto giusto, quindi è un bene che tu sappia la teoria ;

    Passando al codice principale:
    1) fai riferimento a "self" che dovrebbe essere un'istanza di una classe, ma sei fuori da tutte le classi. Ti ricordo che "self" è l'istanza della classe in cui ti trovi, se scritta al difuori di una classe non fa riferimento a nulla. (vedi la dichiarazione dello switch)

    2) ricordati di creare le istanza delle classe quando le vuoi usare (manca l'oggetto "Calendario")

    3) per evitare che il programma ti dica che non hai implementato qualche oggetto o variabile (errore "...is not define") dichiara tutto all'inizio e inizializza solo in seguito (se non sei sicuro di come fare, lascia perdere questo punto)

    per ora è tutto, Buon lavoro.
  • Re: Classe per sostituire aree dello schermo

    Ciao e grazie per i suggerimenti, ci rifletto un po' per modificare il codice e poi te lo mostro.
    Nel frattempo ti posso dire che per ovviare ai limiti della classe che non può essere richiamata dall'esterno, l'avevo inserita in un modulo successivamente importato. Come si fa ad esempio per ''import random''. Il problema qui è che si creano due finestre distinte.

    ps: se il codice con la teoria (il secondo) è corretto, mi chiedo come è che poi sbaglio T_T
Devi accedere o registrarti per scrivere nel forum
4 risposte