Tlinter button command bağlama

Otomatik buton oluşturdum fakat buttonlara bastığımda command=işlem fonksiyonuna gönderi koyduğumda commandde otomatik çalışıyor. Fakat butona bastığımda buttonun karşılığını beceremedim. Bir mantık hatam var. Bu konuda bilgi sahibi olan arkadaşlardan yardım istiyorum. Oluşturduğum butona bastığımda değeri yazdıramadım. Butonları tel tek tanımlarsam oluyor oda kodu büyütüyor.

import tkinter as tk
from tkinter import *
import math
from sympy import sympify
pencere=tk.Tk()
pencere.title(“hesap Makinası”)
pencere.geometry(“350x3500”)
pencere.configure(background=“black”)
tablo=[“C”,“%”,“√”,“÷”,“7”,“8”,“9”,“x”,“4”,“5”,“6”,“-”,“1”,“2”,“3”,“+”,“.”,“0”,“⌫”,“=”]
x_konum = 60
y_konum = 900
ekran=tk.Label(text=“Calculator”,font="Arial 16 ",fg=“orange”,bg=“black”,bd=50)
ekran.place(x=0,y=0)

ekrani=tk.Label(text=“İşlemler :”,font="Arial 16 ",fg=“magenta”,bg=“black”,bd=50)
ekrani.place(x=10,y=150)

ekranit=tk.Label(text=“”,font="Arial 16 ",fg=“white”,bg=“black”)
ekranit.place(x=50,y=350)

result=tk.Label(text=“”,font="Arial 16 ",fg=“white”,bg=“black”)
result.place(x=50,y=650)

ekrans=tk.Label(text="Sonuç : ",font="Arial 16 ",fg=“yellow”,bg=“black”,bd=50)
ekrans.place(x=20,y=450)

def islem(isl):
#ekran[“text”]=ekran[“text”]+sy0[“text”]
return
def sonuc(snc):
return
sayi = 0
for i in range(5):
for j in range(1,5):
if not tablo[sayi].isdigit():#j==4:
tk.Button(text=tablo[sayi],font=“Arial 20 bold”,bg=“green”,fg=“white”,bd=15,activebackground=“red”,activeforeground=“white”).place(x=x_konum, y=y_konum, width=200, height=200)
else:
tk.Button(text=tablo[sayi],font=“Arial 20 bold”,bg=“black”,fg=“white”,bd=15,activebackground=“orange”).place(x=x_konum, y=y_konum, width=200, height=200)
sayi += 1
x_konum += 250
x_konum = 60
y_konum += 250
pencere.mainloop()
“”"
tk.Button(text=tablo[sayi],font=“Arial 20 bold”,bg=“green”,fg=“white”,bd=15,activebackground=“red”,activeforeground=“white”,command=islem(tablo[sayi])).place(x=x_konum, y=y_konum, width=200, height=200)

command=(lambda: islem(tablo[sayi])) gibi bir sey olmasi gerekmiyor mu?

Late binding¹ yuzunden sayi her zaman loop’un sonundaki degeri aldigindan dolayi o da calismayacaktir:

>>> fs = []
>>> for i in range(5):
...     fs.append(lambda: print(i))
... 
>>> fs[0]()
4
>>> fs[1]()
4

Bu yuzden butun degeri bir (lambda x: ...)(x) parantezine almak, x’in iceride dogru degerle var olmasini saglayacaktir:

>>> fs2 = []
>>> for i in range(5):
...     fs2.append((lambda i: (lambda: print(i)))(i))
... 
>>> fs2[0]()
0
>>> fs2[1]()
1

Bazi dokumanlar daha basitce, degiskeni bir parametrenin varsayilan degeri olarak koymayi oneriyor:

>>> fs3 = []
>>> for i in range(5):
...     fs3.append(lambda i=i: print(i))
... 
>>> fs3[0]()
0
>>> fs3[1]()
1

Ama kanaatimce cift lambda’li ornegi anlamak daha kolay ve faydali.


1: Aslen “capture by reference” daha dogru bir terim, fakat “late binding” Python icin daha guzel arama sonuclari donduruyor. Mesele, lambda’nin yarattigi closure’un sayi veya i gibi degerleri referans (isim) olarak tutmasi. Degerin alinip lambda’ya paslanmasi cagri anina kadar olmadigi icin, degiskenin cagri anindaki degeri kullaniliyor:

>>> sayi = 0
>>> f = lambda: print(sayi)
>>> f()
0
>>> sayi = 42
>>> f()
42

Bir fonksiyon yaratip degiskeni ona arguman olarak vermek, degiskenin referans yerine deger olarak tutulmasini sagliyor:

>>> fc = lambda sayi_deger: (lambda: print(sayi_deger))
>>> sayi = 0
>>> f = fc(sayi)
>>> f()
0
>>> sayi = 42
>>> f()
0

(Cunku Python’da sayilar deger olarak paslaniyor.)

2 Beğeni

Teşekkürler. Ben 1 yıldır pythonla ilgikenen eskinin basic, cobol,algol, pascak ve en son C+ kullanan biriyim. Python çok cazip geldi. Bu kodu yazdım ama her butonu ayrı her yazdırmayı ayrı def ile tanımladım. Çaluşıyor. Hadi dedim kodun kısası majbul önce otomatik buton sonrada buton isimleri iş görür dedim ama en son text alıyor ve kalıyor. Sanki butonlar hayalet gibi kaldı. Dediğinizi deneyeceğim. Teşekkürler..

Lambda ile denedim ama list out of index aldım hala bıton commandi görmüyor.

import tkinter as tk
from tkinter import *
import math
from sympy import sympify
tk=Tk()
tk.title(“hesap Makinası”)
tk.geometry(“350x3500”)
tk.configure(background=“black”)
tablo=[“C”,“%”,“√”,“÷”,“7”,“8”,“9”,“x”,“4”,“5”,“6”,“-”,“1”,“2”,“3”,“+”,“.”,“0”,“⌫”,“=”]
x_konum = 60
y_konum = 900
ekran=Label(tk,text=“Calculator”,font="Arial 16 ",fg=“orange”,bg=“black”,bd=50)
ekran.place(x=0,y=0)

ekrani=Label(tk,text=“İşlemler :”,font="Arial 16 ",fg=“magenta”,bg=“black”,bd=50)
ekrani.place(x=10,y=150)

ekranit=Label(tk,text=“”,font="Arial 16 ",fg=“white”,bg=“black”)
ekranit.place(x=50,y=350)

result=Label(tk,text=“”,font="Arial 16 ",fg=“white”,bg=“black”)
result.place(x=50,y=650)

ekrans=Label(tk,text="Sonuç : ",font="Arial 16 ",fg=“yellow”,bg=“black”,bd=50)
ekrans.place(x=20,y=450)

def islem(tab):
#ekran[“text”]=ekran[“text”]+sy0[“text”]
ekranit[“text”]=ekranit[“text”]+tab
return
def sonuc(snc):
return
sayi = 0
for i in range(5):
for j in range(1,5):
if not tablo[sayi].isdigit():
#btn=str(tablo[sayi])
Button(tk,text=tablo[sayi],font=“Arial 20 bold”,bg=“green”,fg=“white”,bd=15,activebackground=“red”,activeforeground=“white”,command=lambda : islem(tablo[sayi])).place(x=x_konum, y=y_konum, width=200, height=200)
else:
#btn=str(tablo[sayi])
Button(tk,text=tablo[sayi],font=“Arial 20 bold”,bg=“black”,fg=“white”,bd=15,activebackground=“orange”,command=lambda : islem(tablo[sayi])).place(x=x_konum, y=y_konum, width=200, height=200)
sayi += 1
x_konum += 250
x_konum = 60
y_konum += 250
tk.mainloop()

Kodu suraya gore duzenlerseniz, uzerinde konusmasi/deneme yapmasi mumkun olabilir.

tablo[sayi]'da bir sikinti olabilir; hata mesaji, hatanin nerede oldugunu soyleyecektir.

Butonlari tek tek nasil tanimliyorsunuz? Oradan da ilerlenebilir.

  • Kodu konu dışında nereye yapıştırmam gerektiği için bakıyorum ama göremedim. Kimseye zorluk çıksrmak gibi bir derdim yok. Python koduma yazbel ihtihza ile başladım. O yüzden yazbele sorunları iletiyorum. Yazbelin tüm dökümanşarını baştan sona okuyup tüm kodlarıda uygulama ile yaptım. Burada bir kaç kete yapıştırdığım kodu konu dışında özel kodların konulduğu bir yeri göremedim.
    Kodumu aşağıdaki aralığa yapıştırırken bir ayraç mı kullanmam gerekiyor. Zaten kod import ile başlayıp mainloop() bitiyor. Sadece tablar kayboluyor bunu önlemenin bir yolu var mı ?
    Bu kodları android telefonda pyroid3 ile yazıyor ve çalıştırıyorum.
    Eğer sizi rahatsız ediyorsa görmezden gelebilirsiniz.
    #######program başlangıcı

import tkinter as tk
from tkinter import *
import math
from sympy import sympify

tk=Tk()
tk.title(“hesap Makinası”)
tk.geometry(“350x3500”)
tk.configure(background=“black”)

tablo=[“C”,“%”,“√”,“÷”,“7”,“8”,“9”,“x”,“4”,“5”,“6”,“-”,“1”,“2”,“3”,“+”,“.”,“0”,“⌫”,“=”]
buton=
x_konum = 60
y_konum = 900

ekran=Label(tk,text=“Calculator”,font="Arial 16 ",fg=“orange”,bg=“black”,bd=50)
ekran.place(x=0,y=0)

ekrani=Label(tk,text=“İşlemler :”,font="Arial 16 ",fg=“magenta”,bg=“black”,bd=50)
ekrani.place(x=10,y=150)

ekranit=Label(tk,text=“”,font="Arial 16 ",fg=“white”,bg=“black”)
ekranit.place(x=50,y=350)

result=Label(tk,text=“”,font="Arial 16 ",fg=“white”,bg=“black”)
result.place(x=50,y=650)

ekrans=Label(tk,text="Sonuç : ",font="Arial 16 ",fg=“yellow”,bg=“black”,bd=50)
ekrans.place(x=20,y=450)

def islem(tab):
#ekran[“text”]=ekran[“text”]+sy0[“text”]
ekranit[“text”]=ekranit[“text”]+tab
return

def sonuc(snc):
return
#otomatik buton oluşturuluyor…
sayi = 0
for i in range(5):
for j in range(1,5):
if not tablo[sayi].isdigit():
btn=str(tablo[sayi])
btn=Button(tk,text=tablo[sayi],
font=“Arial 20 bold”,bg=“green”,
fg=“white”,bd=15,
activebackground=“red”,
activeforeground=“white”,
command=lambda :
islem(tablo[sayi])).place
(x=x_konum, y=y_konum,
width=200, height=200)
else:
btn=str(tablo[sayi])
btn = Button(tk,text=tablo[sayi],
font=“Arial 20 bold”, bg=“black”,
fg=“white”,bd=15,
activebackground=“orange”,
command=lambda :
islem(tablo[sayi])).
place(x=x_konum, y=y_konum,
width=200, height=200)
sayi += 1
x_konum += 250
x_konum = 60
y_konum += 250
tk.mainloop()

########program sonu

Kodu seçip </> butonunu (veya CTRL+E kısayolunu) kullanmak. Yapistirdiginiz yerin uzerinde var.

Tablarin kaybolmasi onemli, cunku python kod bloklarini tablar ile belirliyor.

Ok…ben koflarımı android ortamında yazıyorum. Param olunca laptop alınca bazı şeyler daha kolay olacak. Edit yaptığımda kodu orijinal görüyorum. Ama göndere basınca kod bozuluyor.
aralığa kopyaladım.

``import tkinter as tk
from tkinter import *
import math
from sympy import sympify
tk=Tk()
tk.title(“hesap Makinası”)
tk.geometry(“350x3500”)
tk.configure(background=“black”)
tablo=[“C”,“%”,“√”,“÷”,“1”,“2”,“3”,“*”,“4”,“5”,“6”,“-”,“7”,“8”,“9”,“+”,“.”,“0”,“⌫”,“=”]

buton=
x_konum = 60
y_konum = 900
ekran=Label(tk,text=“Calculator”,font="Arial 15 bold ",fg=“yellow”,bg=“black”,bd=50)
ekran.place(x=0,y=0)

#işlemlerin göründüğü yer
ekrani=Label(tk,text=“İşlemler :”,font=“Arial 20 bold”,fg=“magenta”,bg=“black”,bd=50)
ekrani.place(x=10,y=150)

ekranit = Label(tk, text=“”, font=“Arial 20 bold”, fg=“white”, bg=“black”, anchor=“e”)
ekranit.place(x=10, y=350, width=780, height=150)

#sonuç kısmı
ekrans=Label(tk,text="Sonuç : ",font=“Arial 20 bold”,fg=“orange”,bg=“black”,bd=50)
ekrans.place(x=20,y=475)

result=Label(tk,text=“”,font=“Arial 20 bold”,fg=“white”,bg=“black”)
result.place(x=50,y=675)

def yüzdeal(txt):
yüz=txt
syüz=“”
for v in yüz:
if v !=“%”:
syüz=syüz+v
else:
syüz=syüz+“*”
#result[“text”]=float(sympify(syüz)/100)
result[“text”]=float(eval(syüz)/100)

def kökal(kök):
k=int(bilgi[1:])
result[“text”]=round(float(math.sqrt(k)),2)

giris=“”
bilgi=“”
def hesapla():
global giris
global bilgi
try:
# '% ve √ işareti için özel durum
for i in giris:
if i==“%”:
yüzdeal(bilgi)
return
elif i==“√”:
kökal(bilgi)
return
#giris = giris.replace(“%”, “/100”)
sonuc = str(eval(giris))
result.config(text=sonuc)
giris = sonuc
except:
result.config(text=“Hata”)
giris = “”

def temizle():
global giris
giris = “”
ekranit.config(text=“”)
result.config(text=“”)

def islem(karakter):
global giris
global bilgi
if karakter==“⌫”:
giris=giris[:-1]
ekranit.config(text=giris)
else:
giris += str(karakter)
ekranit.config(text=giris)
bilgi=giris

sayi = 0
for i in range(5):
for j in range(1,5):
text=tablo[sayi]
if text == ‘=’:
command = hesapla
elif text == ‘C’:
command = temizle
else:
command = lambda txt=text: islem(txt)
if not tablo[sayi].isdigit():
Button(tk,text=text,font=“Arial 20 bold”,bg=“green”,fg=“white”,bd=15,activebackground=“red”,activeforeground=“white”,command=command).place(x=x_konum, y=y_konum, width=200, height=200)
else:
Button(tk,text=text,font=“Arial 20 bold”,bg=“black”,fg=“white”,bd=15,activebackground=“orange”,command=command).place(x=x_konum, y=y_konum, width=200, height=200)
sayi += 1
x_konum += 250
x_konum = 60
y_konum += 250
tk.mainloop()``

Merhaba, kodunuz üzerinde düzeltme yapmayacağım, fakat size fikir vermek açısından;

örneğine bakabilirsiniz.

Arayüz tasarımı ve event driven control mantığını kavramanız gerekir.

Yine chatgpt ye rica ettim örnek bir bilimsel hesap makinesi kodu yazdı:

import tkinter as tk
import math

class ScientificCalculator:
    def __init__(self, root):
        self.root = root
        self.root.title("Bilimsel Hesap Makinesi")
        self.root.geometry("400x600")
        self.expression = ""

        self.input_text = tk.StringVar()

        self.create_widgets()

    def create_widgets(self):
        # Giriş ekranı
        input_frame = tk.Frame(self.root, bd=10)
        input_frame.pack()

        input_field = tk.Entry(input_frame, font=('Arial', 20), textvariable=self.input_text, justify='right', bd=10, relief='ridge')
        input_field.grid(row=0, column=0, ipadx=8, ipady=20, columnspan=5)

        # Tuş takımı
        button_frame = tk.Frame(self.root)
        button_frame.pack()

        buttons = [
            ['(', ')', '√', 'x²', 'C'],
            ['sin', 'cos', 'tan', 'log', 'ln'],
            ['7', '8', '9', '/', 'π'],
            ['4', '5', '6', '*', 'e'],
            ['1', '2', '3', '-', '^'],
            ['0', '.', '=', '+', 'DEL']
        ]

        for i, row in enumerate(buttons):
            for j, button in enumerate(row):
                tk.Button(button_frame, text=button, width=6, height=2, font=('Arial', 14),
                          command=lambda b=button: self.on_button_click(b)).grid(row=i, column=j, padx=5, pady=5)

    def on_button_click(self, char):
        if char == 'C':
            self.expression = ""
        elif char == 'DEL':
            self.expression = self.expression[:-1]
        elif char == '=':
            try:
                # ifadesi güvenli değerlendir
                self.expression = self.safe_eval(self.expression)
            except Exception:
                self.expression = "Hata"
        elif char == 'π':
            self.expression += str(math.pi)
        elif char == 'e':
            self.expression += str(math.e)
        elif char == '√':
            self.expression += "math.sqrt("
        elif char == 'sin':
            self.expression += "math.sin(math.radians("
        elif char == 'cos':
            self.expression += "math.cos(math.radians("
        elif char == 'tan':
            self.expression += "math.tan(math.radians("
        elif char == 'log':
            self.expression += "math.log10("
        elif char == 'ln':
            self.expression += "math.log("
        elif char == 'x²':
            self.expression += "**2"
        elif char == '^':
            self.expression += "**"
        else:
            self.expression += str(char)

        self.input_text.set(self.expression)

    def safe_eval(self, expr):
        return str(eval(expr, {"math": math, "__builtins__": {}}))

# Uygulamayı başlat
if __name__ == "__main__":
    root = tk.Tk()
    calc = ScientificCalculator(root)
    root.mainloop()

Bana bilimsel bir hesap makinesini TKinter arayüzünde yazar mısın dedim ve yukarıdaki kodu verdi.

Ve merak ettiğiniz soruyu sordum:

Burada buton event lerini nasıl bir yaklaşımla kullandın?

Cevap verdi:

Çok güzel bir soru! Bu kodda butonlara tıklama olaylarını yönetmek için lambda fonksiyonları ile dinamik olarak her butona özel bir işlev bağladım. Gel birlikte detaylı bakalım:

🧠 Butonların Event (Olay) Yönetimi Mantığı
Kodda şu satır kilit noktadır:

python
Copy
Edit
command=lambda b=button: self.on_button_click(b)
Bu satır, her bir buton için command parametresine bir lambda fonksiyonu tanımlar. Bu fonksiyon çalıştığında self.on_button_click(b) fonksiyonu çağrılır ve butonun metni (button) argüman olarak aktarılır.

👇 Adım Adım Açıklama
Örnek olarak butonlar listesinde bir sin butonu var. Bu kod:

python
Copy
Edit
tk.Button(button_frame, text='sin', ..., command=lambda b='sin': self.on_button_click(b))
gibi çalışır ve tıklanıldığında on_button_click('sin') fonksiyonu çağrılır.

🧩 Neden lambda b=button?
Eğer doğrudan lambda: self.on_button_click(button) yazsaydık, tüm butonlar en son butonun değerini alırdı (bu Python'un "late binding" davranışı). Bu yüzden:

python
Copy
Edit
lambda b=button: self.on_button_click(b)
şeklinde yazılarak her bir butonun kendi değerini saklaması sağlanır.

✅ Bu Yaklaşımın Avantajları
Kod tekrarını azaltır: Tek tek her buton için def ... tanımlamana gerek kalmaz.

Dinamik butonlar için idealdir: Butonları bir liste/dizi ile tanımlayıp döngüde işleyebilirsin.

Çok okunaklı ve kısa: İşlevselliği tek bir satırda tanımlayabiliyorsun.

İstersen bu yapıyı daha modüler hale getirebilir veya buton fonksiyonlarını ayrı metodlara bölerek kod okunabilirliğini daha da artırabiliriz. Yardımcı olayım mı bu konuda?

Açıklamalar bunlar.

Burada sizin kodunuzu incelememin nedeni şu.

Önce kodda hangi yaklaşımı uyguladığınızı araştırmakla vakit harcayacaktık. Doğru yada yanlış bir yaklaşım mı tartışma konusu olacaktı. Bu arada size birden çok soru sormak zorunda kalacaktık.

En basiti amerikayı yeniden keşfetmeden. Neden hesap makinesi kodu yazılır yöntemler nelerdir bakmak. Bunu yaptığınız takdirde daha az soru sorarak kendiniz balık tutabiirsiniz.

Kolay gelsin.