Topic: Tkinter e menu  (Letto 235 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline ElTriestin

  • python unicellularis
  • *
  • Post: 1
  • Punti reputazione: 0
    • Mostra profilo
Tkinter e menu
« il: Marzo 11, 2019, 21:17 »
Ciao a tutti
Ho scritto una piccola GUI con Tkinter per la gestione ipotetica di una libreria e la domanda è:
una volta creato il menù, selezionando per esempio "NUOVO LIBRO", vorrei visualizzare 4 campi di testo con label per la decrizione/inserimento dei dati che mi interessano (titolo, autore, ecc..)
Suppongo di dover creare una funzione che "disegni" campi di testo e label con poi il salvataggio dei valori in una tabella MySQL (il programma già funziona in shell, anche se non mi soddisfa perchè la visualizzazione degli elenchi in shell non è pratica)

Di seguito il codice. Grazie in anticipo

from tkinter import *
import tkinter.messagebox as tm

class LoginFrame(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.label_nome_utente = Label(self, text="Nome Utente")
        self.label_password = Label(self, text="Password")
        self.entry_nome_utente = Entry(self)
        self.entry_password = Entry(self, show="*")
        self.label_nome_utente.grid(row=0, sticky=E)
        self.label_password.grid(row=1, sticky=E)
        self.entry_nome_utente.grid(row=0, column=1)
        self.entry_password.grid(row=1, column=1)
        self.logbtn = Button(self, text="Login", command=self._login_btn_clicked)
        self.logbtn.grid(columnspan=2)
        self.pack()

    def _login_btn_clicked(self):
        nome_utente = self.entry_nome_utente.get()
        password = self.entry_password.get()

        if nome_utente == "marco" and password == "password":
            tm.showinfo("Informazioni", "Benvenuto Marco")
            root.destroy()
            windows = Tk()
            windows.title("pyLibri 1.0")
            windows.geometry("960x640")
            barra_menu=Menu(windows)
            windows.config(menu=barra_menu)
            menu_libri=Menu(barra_menu)
            barra_menu.add_cascade(label="Libri",menu=menu_libri)
            menu_libri.add_command(label="Nuovo libro")
            menu_libri.add_command(label="Cerca libro")
            menu_libri.add_command(label="Cancella libro")
            menu_soci=Menu(barra_menu)
            barra_menu.add_cascade(label="Soci",menu=menu_soci)
            menu_soci.add_command(label="Nuovo socio")
            menu_soci.add_command(label="Cerca socio")
            menu_soci.add_command(label="Cancella socio")
            menu_prenotazioni = Menu(barra_menu)
            barra_menu.add_cascade(label="Prenotazioni", menu=menu_prenotazioni)
            menu_prenotazioni.add_command(label="Nuova prenotazione")
            menu_prenotazioni.add_command(label="Cerca prenotazione")
            menu_prenotazioni.add_command(label="Cancella prenotazione")
            menu_uscita = Menu(barra_menu)
            barra_menu.add_cascade(label="Uscita", menu=menu_uscita)
            menu_uscita.add_command(label="Esci", command=quit)

        else:
            tm.showerror("Errore", "Nome utente o password errata")


root = Tk()
root.title("pyLibri 1.0")
lf = LoginFrame(root)
root.mainloop()

Offline nuzzopippo

  • python habilis
  • **
  • Post: 56
  • Punti reputazione: 0
    • Mostra profilo
Re:Tkinter e menu
« Risposta #1 il: Marzo 13, 2019, 19:59 »

Ciao @ElTriestin, benvenuto.

È un paio di giorni  che guardo questo post, aspettando gli utenti esperti, per imparare dalla Loro risposta, dato che non si vedono oso proporre io una risposta, pur avendo fatto un solo tentativo di programmare GUI in python e presto convintomi che ho molto da imparare "prima" di ritentare.

Veniamo alla Tua domanda :
Ciao a tutti
...Suppongo di dover creare una funzione che "disegni" campi di testo e label con poi il salvataggio dei valori in una tabella MySQL (il programma già funziona in shell, anche se non mi soddisfa perchè la visualizzazione degli elenchi in shell non è pratica)

Sarà solo una mia opinabile opinione ma non credo proprio sia conveniente l'utilizzo di "funzioni" nella programmazione di interfacce grafiche, ritengo molto più indicato l'utilizzo di classi.
Vedo nel Tuo codice una tendenza alla creazione "dinamica" delle interfacce ... si può fare ma, secondo me, ci si complica la vita, in primo luogo, poi credo anche Ti renda impossibile ciò che vuoi fare : che fine fanno i widget che vorresti sostituire (faccenda implicita nella struttura) e come li trovi per gestirli?
Faccenda complessa questa, costringerebbe a tener traccia di una enormità di controlli (per testi, anagrafiche, prentazioni, etc.) e gestirli, molto meglio pensare a finestre specializzate per i vari aspetti operativi e magari una principale per la visualizzazione dei dati imho.

In ogni caso, trovo "improprio" distruggere Tk e ricrearlo, non sarebbe meglio dedicarlo alla finestra principale e nasconderlo per mostrarlo dopo il login?, quest'ultimo potrebbe essere fatto tramite una finestra Toplevel, p.e.

 ... comunque ho dedicato un'oretta a tirar fuori un esempio funzionante sulla base del Tuo codice eseguire la visualizzazione per un "Nuovo libro" (solo per titolo ed autore) facendo la relativa selezione da menu, preparato un "oggetto" per detta visualizzazione ed una funzione di classe preposta (        _carica_libro) la variante alle istruzioni da Te poste è semplicemente
        menu_libri.add_command(label='Nuovo libro', command=self._carica_libro)

il richiamo della funzione alla definizione del command

C'è un però, bisogna eliminare prima ciò che viene sostituito, guardati la classe "FinestraPrincipale" e l'uso della variabile di istanza "self.sfondo", credo che applicata alle altre "visualizzazioni" dovrebbe funzionare ... anche se personalmente eviterei di utilizzare una tale metodica.

Sotto il codice da me fatto (con le considerazioni di sopra), spero possa esserti utile

# -*- coding: utf-8 -*-

import tkinter as tk
import tkinter.messagebox as tm

# *** CLASSI DEI PANNELLI ***

class FrmLibro(tk.Frame):
    ''' Pannello dei libri.'''
   
    def __init__(self, master, *a, **k):
        super().__init__(master, *a, **k)
        self.master = master
        subf1 = tk.Frame(self, padx=5, pady=5)
        subf1.pack(expand=True, fill='x', padx=5, pady=5)
        lbl1 = tk.Label(subf1, text='Titolo :', width=7, justify='left')
        lbl1.pack(side='left', anchor='n')
        self.titolo = tk.Entry(subf1, width=15)
        self.titolo.pack(side='left', expand=True, fill='x', anchor='n')
        subf2 = tk.Frame(self, padx=5, pady=5)
        subf2.pack(expand=True, fill='x', padx=5, pady=5)
        lbl2 = tk.Label(subf2, text='Autore :', width=7, justify='left')
        lbl2.pack(side='left', anchor='n', padx=5, pady=5)
        self.autore = tk.Entry(subf2, width=15)
        self.autore.pack(side='left', expand=True, fill='x', anchor='n', padx=5, pady=5)
       

# *** CLASSI DELLE FINESTRE ***

class LoginFrame(tk.Toplevel):
   
    def __init__(self, master=None):
        self.master = master
        super().__init__(self.master)
        self.label_nome_utente = tk.Label(self, text="Nome Utente")
        self.label_password = tk.Label(self, text="Password")
        self.entry_nome_utente = tk.Entry(self)
        self.entry_password = tk.Entry(self, show="*")
        self.label_nome_utente.grid(row=0, sticky=tk.E)
        self.label_password.grid(row=1, sticky=tk.E)
        self.entry_nome_utente.grid(row=0, column=1)
        self.entry_password.grid(row=1, column=1)
        self.logbtn = tk.Button(self, text="Login", command=self._login_btn_clicked)
        self.logbtn.grid(columnspan=2)
        self.update()
        centra_finestra(self)
       
    def _login_btn_clicked(self):
        nome_utente = self.entry_nome_utente.get()
        password = self.entry_password.get()

        if nome_utente == "marco" and password == "password":
            self.destroy()
            self.master.mostra()
        else:
            self.master.chiudi()


class FinestraPrincipale(tk.Tk):
   
    def __init__(self):
        super().__init__()
        # configurazione
        self.title('pyLibri 0.1')
        self.geometry('960x640')
        barra_menu = tk.Menu(self)
        self.config(menu=barra_menu)
        menu_libri = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Libri', menu=menu_libri)
        menu_libri.add_command(label='Nuovo libro', command=self._carica_libro)
        menu_libri.add_command(label='Cerca libro')
        menu_libri.add_command(label='Cancella libro')
        menu_soci = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Soci', menu=menu_soci)
        menu_soci.add_command(label='Nuovo socio')
        menu_soci.add_command(label='Cerca socio')
        menu_soci.add_command(label='Cancella socio')
        menu_prenotazioni = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Prenotazioni', menu=menu_prenotazioni)
        menu_prenotazioni.add_command(label='Nuova prenotazione')
        menu_prenotazioni.add_command(label='Cerca prenotazione')
        menu_prenotazioni.add_command(label='Cancella prenotazione')
        menu_uscita = tk.Menu(barra_menu)
        barra_menu.add_cascade(label='Uscita', menu=menu_uscita)
        menu_uscita.add_command(label='Esci', command=self.destroy)
        self.sfondo = tk.Frame(self, padx=0, pady=0)
        self.sfondo.pack(expand=True, fill='both', padx=0, pady=0)
        self.nascondi()
        LoginFrame(self)
       
    def nascondi(self):
        ''' Nasconde la finestra.'''
        self.withdraw()

    def mostra(self):
        ''' Mostra la finestra '''
        self.deiconify()
        centra_finestra(self)
   
    def chiudi(self):
        ''' Chiude la finestra.'''
        tm.showerror("Errore", "Nome utente o password errata")
        self.destroy()
   
    def _carica_libro(self):
        self.sfondo.destroy()
        self.sfondo = FrmLibro(self, padx=0, pady=0)
        self.sfondo.pack(expand=True, fill='both', padx=0, pady=0)
       
       

# *** FUNZIONI GLOBALI ****

def centra_finestra(gui):
    ''' Centra una finestra, passata come parametro, sullo schermo '''
    l = gui.winfo_screenwidth()
    a = gui.winfo_screenheight()
    wx = gui.winfo_width()
    wy = gui.winfo_height()
    gui.geometry('{}x{}+{}+{}'.format(wx, wy, (l-wx)//2, (a-wy)//2))

# *** START APPLICAZIONE ***

if __name__ == '__main__':
    app = FinestraPrincipale()
    app.mainloop()