Perché usare le classi quando si programma una GUI tkinter in Python


19

Ho programmato principalmente in Python e ho programmato un paio di GUI con Tkinter, ogni tutorial che abbia mai visto ha raccomandato di definire e utilizzare una classe per la GUI, ma la mia GUI funziona perfettamente usando solo procedure, senza una classe.

Perché usare una classe? Dal mio punto di vista sembra essere semplicemente un ulteriore livello di complessità e codice non necessario.

Risposte:


19

Perché usare una classe? Perché semplifica il lavoro, supponendo che tu sappia come eseguire la programmazione orientata agli oggetti e supponendo che tu stia scrivendo una GUI non banale. L'uso degli oggetti consente di dividere facilmente il codice in unità modulari che sono autosufficienti e la modularizzazione del codice è generalmente considerata una buona pratica.

La programmazione della GUI si presta prontamente a uno stile orientato agli oggetti, poiché una GUI è composta interamente da oggetti: etichette, pulsanti, barre di scorrimento, aree di testo, ecc. Dato che stai già utilizzando oggetti, organizzare il tuo codice in oggetti più grandi ha senso . La barra degli strumenti è un oggetto, la barra di stato è un oggetto, il riquadro di navigazione è un oggetto, l'area principale è un oggetto, ogni scheda del blocco note è un oggetto e così via.

Anche quando il tuo codice non è molto complesso, da un punto di vista più pratico ti consente di definire associazioni e callback prima nel file rispetto alla definizione della funzione che stai chiamando, che penso abbia molto senso.

Ad esempio, considera un semplice esempio (supponendo che tkinter sia stato importato come import tkinter as tk(python3) o import Tkinter as tk(python2):

def quit(event=None):
    sys.exit()
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.pack()
label.bind("<1>", quit)
root.mainloop()

Per me, il flusso di quel codice è tutto sbagliato. Devo definire il metodo quit prima di fare riferimento a esso, e la creazione della finestra principale e la chiamata a mainloop sono separate da tutto l'altro codice.

Utilizzando le classi, tuttavia, posso scrivere il codice in un ordine più naturale:

class MyWindow(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Hello, world")
        label.pack()
        label.bind("<1>", self.quit)
    def quit(self, event=None):
        sys.exit()

root = tk.Tk()
MyWindow(root).pack()
root.mainloop()

Il corpo principale della GUI si trova nella parte superiore del file e sotto il codice di supporto. Ora, ovviamente, puoi usare le funzioni per ottenere più o meno la stessa cosa. Secondo me, tuttavia, le lezioni rendono tutto un po 'più semplice.

Un altro vantaggio è che ora posso facilmente cambiare la finestra contenente senza dover cambiare nulla sulla finestra "principale" (e viceversa). Cioè, posso aggiungere bordi o una nuova sezione completa alla GUI principale, ma non devo toccare una singola riga di codice all'interno di MyWindow. In contrasto con il codice procedurale in cui potrebbe essere necessario modificare l' label.pack()istruzione e le istruzioni pack (o grid) di tutti gli altri widget nell'interfaccia utente.

Detto questo, tuttavia, non è necessario utilizzare un approccio orientato agli oggetti per scrivere codice valido, pulito e gestibile. Esso può essere, ma può anche portare a codice poveri. Alla fine della giornata, un approccio orientato agli oggetti è solo uno strumento. Se lo usi o meno e se lo usi correttamente o meno dipende da molti fattori. Quindi potrebbe benissimo essere per te, e per il codice che scrivi, uno stile funzionale è perfettamente accettabile. Penso che scoprirai che man mano che i tuoi programmi diventano più complessi, un approccio orientato agli oggetti renderà più semplice l'organizzazione e la manutenzione del tuo codice.


Perché hai usato un Frame nel secondo esempio? Non potresti evitarlo come hai fatto nel primo esempio? C'è qualche segreto dietro l'utilizzo di Frame con le classi?
multigoodverse

2
Il telaio è semplicemente per comodità. Non esiste un segreto per ereditare da Frame. Avrei potuto ereditare da objectqualsiasi altra classe, ma in genere finisco per creare comunque un frame. Se sto mettendo tutto in una cornice, ha senso trasformare la classe in una cornice. .
Bryan Oakley,

1
Ha senso, grazie! Inoltre, ho visto gli altri usare self prima delle variabili, ma vedo che stai usando qualcosa come label=tk.Label()invece di self.tk.Label(). È una scelta di stile? Ecco un esempio usando self: python-textbok.readthedocs.org/en/1.0/…
multigoodverse

1
@BryanOakley, suppongo che intendevi usare parent invece di root nella seguente riga di MyWindow .__ init__: "label = tk.Label (root, text =" Hello, world ")"
user3885927

1
@ user3885927: sì! Caspita, ci sono voluti quasi tre anni perché qualcuno se ne accorgesse. parentTuttavia , non ma piuttosto self, poiché la classe stessa è un Frame. Grazie!
Bryan Oakley,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.