Tkinter'da bekleme

Merhabalar sorun şu butona basıldığı zaman ok fonksiyonu bitene kadar pencerede hiçbir şey olmuyor, daha doğrusu donup kalıyor.
Yapmak istediğim butona basınca 3 sn sonra 99 yazması 7 sn sonra 78 yazması, ama butona basınca 7 sn donuyor ve 78 basıyor. Bunu çözümü var mı?

import tkinter as tk
import time
def ok():
    time.sleep(3)
    lb['text'] = 99
    time.sleep(4)
    lb['text'] = 78

pencere = tk.Tk()

lb = tk.Label(text=33)
lb.place(x=20, y=20)
b = tk.Button(text='bas', command=ok)
b.place(x=50, y=50)

pencere.mainloop()

Merhaba.

Tkinter kullanırken iki işlem arasında bekleyecekseniz pencere.after kullanmanız daha doğru olur, aksi takdirde arayüzün donması ile alakalı problemler yaşarsınız:

import tkinter as tk
import time

def komut():
    lb["text"] = 99
    pencere.after(4000, lambda: lb.config(text = 78)) # 4000 milisaniye sonra ikinci argüman olan fonksiyon çalışacak

pencere = tk.Tk()

lb = tk.Label(text=33)
lb.place(x=20, y=20)
b = tk.Button(text='bas', command=lambda: pencere.after(3000, komut)) # 3000 milisaniye sonra ikinci argüman olan fonksiyon çalışacak
b.place(x=50, y=50)

pencere.mainloop()

Tabii kodumuzu bu şekilde dağıtıp okunaklılığı azaltmak istemiyorsak ufak hilelere başvurabiliriz:

import tkinter as tk
import time

def wait(f):
    def start():
        g = f()
        def repeater():
            try:
                pencere.after(next(g) * 1000, repeater)
            except StopIteration:
                pass
        repeater()
    return start

@wait
def komut():
    yield 3 # üç saniye bekliyor
    lb["text"] = 99
    yield 4 # dört saniye bekliyor
    lb["text"] = 78

pencere = tk.Tk()

lb = tk.Label(text=33)
lb.place(x=20, y=20)
b = tk.Button(text='bas', command=komut)
b.place(x=50, y=50)

pencere.mainloop()
4 Beğeni

Peki diyelim butona basıldığında 20 den geriye doğru 2 saniye aralıklarla label ile ekrana basmak istiyorum nasıl yaparım bunu?

yield kullanmayı biliyor musunuz?

Dediğiniz şöyle yapılabilir:

import tkinter as tk
import time

def wait(f):
    def start():
        g = f()
        def repeater():
            try:
                pencere.after(next(g) * 1000, repeater)
            except StopIteration:
                pass
        repeater()
    return start

@wait
def komut():
    for i in range(20, 0, -1):
        lb["text"] = i
        yield 2

pencere = tk.Tk()

lb = tk.Label(text=20)
lb.place(x=20, y=20)
b = tk.Button(text='bas', command=komut)
b.place(x=50, y=50)

pencere.mainloop()

yield biliyorum ama yukarıdaki wait fonksiyonuna pek aşina değilim.

Fonksiyon gözünüzün önünde zaten, 10 satırdan ibaret.

Kod her yield’e geldiğinde yanındaki sayı kadar bekleyecek (saniye cinsinde).

Bu örnekteki wait fonksiyonunu sadece komut fonksiyonu için yazmıştım, daha genel bir kullanım için şöyle bir şey yapılabilir:

import tkinter as tk
import time

def wait(f):
    def start(*args, **kwargs):
        g = f(*args, **kwargs)
        widget = next(g)
        
        def repeater():
            try:
                widget.after(next(g) * 1000, repeater)
            except StopIteration:
                pass
        repeater()
        
    return start

@wait
def write(start, end):
    yield root # after metodu çağırılıcak widget'i tek sefere mahsus en başta yield ediyoruz.
    for i in range(start, end):
        print(i)
        yield 1 # 1 saniye bekle

root = tk.Tk()

e1 = tk.Entry()
e2 = tk.Entry()
e1.pack()
e2.pack()

b = tk.Button(text='print numbers', command=lambda: write(int(e1.get()), int(e2.get()))) # artık fonksiyonları çağırırken argüman kullanabiliyoruz
b.pack()

root.mainloop()
2 Beğeni