Python'da bir tkinter gui programlarken neden sınıflar kullanılıyor?


19

Öncelikle python programlıyorum ve Tkinter ile birkaç GUI programladım, gördüğüm her öğretici GUI için bir sınıf tanımlamayı ve kullanmayı önerdi, ancak benim GUI sınıf olmadan sadece prosedürleri kullanarak kusursuz bir şekilde çalışıyor.

Neden bir sınıf kullanmalıyım? Benim bakış açımdan, fazladan bir karmaşıklık ve gereksiz kod katmanı gibi görünüyor.

Yanıtlar:


19

Neden bir sınıf kullanmalıyım? Çünkü işi kolaylaştırır, nesneye yönelik programlama yapmayı bildiğinizi varsayar ve önemsiz olmayan bir GUI yazdığınızı varsayar. Nesneleri kullanmak, kodunuzu kendi kendine yeten modüler birimlere kolayca bölmenize olanak tanır ve kodunuzu modülerleştirmek genellikle en iyi uygulama olarak kabul edilir.

Bir GUI tamamen nesnelerden (etiketler, düğmeler, kaydırma çubukları, metin alanları vb.) Oluştuğu için GUI programlama kolayca nesne yönelimli bir stile sahiptir. Zaten nesneleri kullandığınızdan, kodunuzu daha büyük nesnelere düzenlemek mantıklı . Araç çubuğu bir nesnedir, durum çubuğu bir nesnedir, gezinti bölmesi bir nesnedir, ana alan bir nesnedir, her not defteri sekmesi bir nesnedir vb.

Kodunuz çok karmaşık olmasa bile, daha pratik bir bakış açısından, dosyada, aradığınız işlevin tanımından daha önce bağları ve geri aramaları tanımlamanıza izin verir, bence çok mantıklı.

Örneğin, basit bir örneği düşünün import tkinter as tk(tkinter'ın (python3) veya import Tkinter as tk(python2) gibi içe aktarıldığını varsayarak :

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

Bana göre, bu kodun akışı yanlış. Ben başvurudan önce quit yöntemi tanımlamak zorunda ve kök pencere ve mainloop çağrısı diğer tüm kod ile ayrılır.

Sınıfları kullanarak, ancak, kodu daha doğal bir sırayla yazabilirsiniz:

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

GUI'nin ana gövdesi dosyanın hemen üst tarafındadır ve destek kodu bunun altındadır. Şimdi, elbette, aynı şeyin çoğunu elde etmek için işlevleri kullanabilirsiniz. Benim düşünceme göre, sınıflar her şeyi biraz daha kolaylaştırıyor.

Başka bir avantaj, artık "ana" pencere hakkında hiçbir şey değiştirmek zorunda kalmadan içeren pencereyi kolayca değiştirebilmemdir (ve tam tersi). Yani, ana GUI'ye kenarlıklar veya tamamen yeni bir bölüm ekleyebilirim, ancak MyWindow içindeki tek bir kod satırına dokunmam gerekmiyor. İfadeyi label.pack()ve kullanıcı arayüzündeki diğer tüm widget'ların pack (veya grid) ifadelerini değiştirmeniz gerekebileceği prosedür koduyla karşılaştırın .

Bununla birlikte, söylenenlerin hepsi iyi, temiz ve bakımı kolay bir kod yazmak için nesne yönelimli bir yaklaşım kullanmak zorunda değildir. Bu olabilir , ama aynı zamanda kötü koda sebep olabilir. Günün sonunda, nesne yönelimli bir yaklaşım sadece bir araçtır. Kullanıp kullanmamanız ve doğru kullanıp kullanmamanız birçok faktöre bağlıdır. Bu yüzden çok iyi sizin için olabilir ve kod için size yazma, fonksiyonel tarzı mükemmel kabul edilebilir. Programlarınız daha karmaşık hale geldikçe, nesne yönelimli bir yaklaşımın kodunuzu düzenlemeyi ve korumayı kolaylaştıracağını göreceksiniz.


İkinci örnekte neden bir Çerçeve kullandınız? İlk örnekte yaptığınız gibi bundan kaçınamaz mısınız? Frame'i sınıflarla kullanmanın arkasında bir sır var mı?
multigoodverse

2
Çerçeve kolaylık sağlamak içindir. Frame'den devralmanın bir sırrı yoktur. objectBaşka bir sınıftan veya başka bir sınıftan miras alabilirdim , ama genellikle yine de bir çerçeve oluşturuyorum. Eğer her şeyi bir çerçeveye koyarsam, sınıfı bir çerçeve haline getirmek mantıklıdır. .
Bryan Oakley

1
Mantıklı, teşekkürler! Ayrıca, başkalarının değişkenlerden önce kendini kullandığını gördüm, ama label=tk.Label()bunun yerine bir şey kullandığınızı görüyorum self.tk.Label(). Bu bir stil seçimi mi? Self'i
multigoodverse

1
@BryanOakley, sanırım MyWindow .__ init__'nin aşağıdaki satırında kök yerine üst öğe kullanmak istediniz: "label = tk.Label (root, text =" Merhaba, dünya ")"
user3885927

1
@ user3885927: evet! Vay canına, birisinin bunu fark etmesi neredeyse üç yıl sürdü. Yine de, sınıfın kendisi bir Çerçeve olduğu için parentdeğil self, aksine . Teşekkürler!
Bryan Oakley
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.