Init fonksiyonunda neler olmalı?

Merhaba. Soru biraz abes olabilir ancak anlamak için sormak istedim.

Bazı programların kodlarında init fonksiyonu içerisinde bazı değişkenler self ile tanımlanırken, bazıları ise self olmadan tanımlanıyor. Buradaki ayrımı neye göre yapıyoruz? Örnek bir kod parçası bırakayım mesela:

import tkinter as tk

class Form(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry("500x500)
        self.title("Denemedir!")


form = Form()

Mesela, ben bu şekilde tanımlama yaparken, Form sınıfından bir nesne türettiğim zaman ekranda gözükecek bütün her şeyi içine yazıyorum. Buttonlar, labeller, textler falan… Ama bazıları self olmadan frame tanımlıyor örneğin.

İzah edebilen birisi olursa çok sevinirim. Teşekkürler şimdiden :slight_smile:

Merhaba,

Normalde, tk.Tk sınıfını kullanarak yeni bir sınıfın tanımlandığını çok görmüyorum. Ancak bunun yerine tk.Button, tk.Text vs. vs. widgetlerin özelleştirildiği sınıfların sıklıkla oluşturulduğunu söyleyebilirim.

Örneğin, aşağıda özelleştirilmiş bir tk.Entry sınıfı görüyorsunuz.

import tkinter as tk


class Entry(tk.Entry):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack()
        self.bind(
            sequence="<KeyRelease>",
            func=self.delete_nonnumeric_chars
        )
        
    def delete_nonnumeric_chars(self, event, typ=float):
        try:
            if event.widget.get() != "-":
                if typ == float:
                    float(event.widget.get())
                elif typ == int:
                    int(event.widget.get())
        except ValueError:
            index = event.widget.index("insert")
            event.widget.delete(index - 1, "end")
            
            
root = tk.Tk()
entry = Entry(master=root)
root.mainloop()

Başka bir örnek:

import tkinter as tk


class Button(tk.Button):
    def __init__(self, color, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack()
        self.configure(
            activebackground=self["bg"],
            activeforeground=color,
            borderwidth=0,
            highlightthickness=0,
            font="Default 20",
            fg=color
        )
            
            
root = tk.Tk()
button = Button(master=root, text="Button", color="green")
root.mainloop()

Başka bir örnek:

import tkinter as tk


class EntryFrame(tk.Frame):
    def __init__(self, texts, title, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack()
        self.label = tk.Label(master=self, text=title, fg="red")
        self.label.pack()
        self.frame = tk.Frame(master=self)
        self.frame.pack()
        self.widgets = self.create_widgets(texts=texts)

    def create_widgets(self, texts):
        widgets = {}
        for index, text in enumerate(texts):
            label = tk.Label(master=self.frame, text=text, fg="blue")
            label.grid(row=index, column=0, sticky="w")
            entry = tk.Entry(master=self.frame, width=5)
            entry.grid(row=index, column=1, sticky="w")
            widgets[text] = entry
        return widgets
        
        
root = tk.Tk()
entries = EntryFrame(master=root, texts=["Name", "Surname"], title="Info")
root.mainloop()

Olabilir, self ile yazılmayan değişkenin sınıfın başka bir yerinde kullanılması gerekmiyordur, bu yüzden self olmadan yazmak istemiştir kodu yazan…

1 Beğeni

Hocam, lütfen bilgisizliğimi mazur görün ancak anlamak açısından bir şeyi sormak istiyorum.

Açıkçası ben programın GUI kısmını tek bir class içine almalıyım diye düşünüyordum? Şimdi hal böyleyken, kimi arkadaşlar da yukarıdaki gib class Program(tk.Tk) şeklinde çalışmam gerektiğini söylediler.

Ben de kendimce eğer bu şekilde çalışacaksam ve bu classı örneklediğim anda açılacak formu da düzenleyeceksem, hepsini İnit fonksiyonuna yazmam gerektiğini düşünmüştüm. Mesela:

import tkinter as tk

class Program(tk.Tk):
    def __init__(self):
         super().__init__()
         self.label = tk.Label(text='En üstte yazsın')
         self.label.place=(x=0,y=0)
         self.button = tk.Button(text='Butondur')
         self.button.place(x=0, y= 50)

         #Yani program açıldığı gibi karşıma çıkacak formdaki butonlar, entryler, labeller,
           hepsini örneğe bağımlı bir değişken şeklinde 'self' kullanarak
           init fonksiyonuna dahil ediyordum?

ana_program = Program()

Ancak şimdi söylediğiniz gibi her widgeti ayrı bir sınıf içinde tanımlayıp çalıştığım zaman, bu widgetleri ana formda nasıl çalıştıracağımı bilemedim.

Sizin söylemek istediğiniz şu mantığa mı geliyor: diyelim ki programda üç tane label, on tane buton, beş tane de entry var. Bunları tek tek bir sınıf olarak tanımlayıp örnekleyerek çalışmak daha uygun olur?

Eğer öyleyse bile, bu widgetleri nesneye kopyaladıktan sonra ana_form classında konumlandırmayı nasıl yapabilirim, bilgi verebilirseniz çok sevinirim…

Cevabınız ve ilginiz için çok teşekkürler.

Gerekmiyor, ama alsanız da sorun değil. Arkadaşlarınızın söylediği benim sıklıkla karşılaşmadığım bir tarz. Kişisel olarak ben bu tarzı benimsemiyorum. tk.Tk() çok özelleştirilen bir sınıf değil açıkçası. Bir iki tane özelliği dışında çok fazla bir değişiklik yapılmayan bir sınıf.

Genelde, buttonların hepsini, buttons.py gibi bir dosyanın içinde tutuyorum. Bu dosyanın içinde değişik button classları olabiliyor.

Aynı durum entry için de geçerli.

Hayır benim söylediğim bu anlama gelmiyor. Örnek vermeye çalışayım. Diyelim programda düğme kısmı resim olan düğmelere ihtiyacım var. Bu düğmeler için bir sınıf tanımlıyorum. Benzer bir durum Entry için de geçerli. Yani belirli bir takım özellikleri ile diğerlerinden farklılaşacak olan widgetler için ayrı bir sınıf oluşturuyorum.

Şöyle:

import tkinter as tk


class Entry(tk.Entry):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack()
        
        
class Button(tk.Button):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack()
        
        
class Label(tk.Label):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack()
        
        
root = tk.Tk()
entry = Entry(master=root)
button = Button(master=root, text="Button")
label = Label(master=root, text="Label")
root.mainloop()
1 Beğeni

Hocam bütün class'ları çoklu miras ile tek sınıfta toplamanın bir yolu varmı ?

Yani, hem tk.Button sınıfını hem de tk.Entry sınıfını miras alan bir sınıf tanımlamak istiyorsanız, bunun iyi bir fikir olduğunu söyleyemem.

1 Beğeni
...
def _init(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack()

class Entry(tk.Entry):
    __init__ = _init

class Button(tk.Button):
    __init__ = _init

...

Bir sınıf birden fazla sınıfı miras alabilir. Metot isimleri çakıştığında ilk miras alınan sınıf tercih ediliyor. Bu durumda hem Button hem de Entry sınıfını miras alan bir sınıf ikisinin de bütün özelliklerine sahip olamaz.

3 Beğeni

Hocam zahmet edip cevap verdiğiniz için teşekkür ediyorum :slight_smile: Github hesabınız varsa yazdığınız kodları incelemek isterim.

Rica ederim.

github hesabım

1 Beğeni