7. Standart Bilgi Pencereleri (Standard Dialogs)

Bu bölümün konusu Tkinter’de Standart Bilgi Pencerelerinin kullanımı. Nedir bu “Standart Bilgi Penceresi” denen şey? Diyelim ki bir program yazıyorsunuz... Bu programda herhangi bir işlemle ilgili olarak kullanıcıya bir mesaj göstermek istediğimizde karşımızda iki yol var. Birinci yolda, Tkinter’in Toplevel() aracını kullanarak, göstermek istediğimiz mesajı ve gerekli düğmeleri içeren bir pencere oluşturabiliriz. Hemen bununla ilgili bir örnek verelim:

# -*- coding: utf-8 -*-
from Tkinter import *

pencere = Tk()

def kapat():
    if not entry.get():
        yenipen = Toplevel()

        uyari = Label(yenipen)
        uyari["text"] = "Lütfen geçerli bir e.posta adresi yazın!"
        uyari.pack()

        uybtn = Button(yenipen)
        uybtn["text"] = "Tamam"
        uybtn["command"] = yenipen.destroy
        uybtn.pack()

    else:
        pencere.destroy()

etiket = Label()
etiket["text"] = "e.posta adresiniz:"
etiket.pack()

entry = Entry()
entry.pack()

dgm = Button()
dgm["text"] = "Gönder"
dgm["command"] = kapat
dgm.pack()

pencere.mainloop()

Burada eğer kullanıcı entry() aracına herhangi bir şey yazmadan “gönder” düğmesine basarsa bir uyarı penceresi açılacak ve kullanıcıyı entry() aracına geçerli bir e.posta yazması konusunda uyaracaktır.

Dediğimiz gibi, böyle bir işlev yerine getirmeniz gerekirse yukarıdaki yöntemi kullanabilirsiniz. Ama aslında buna hiç gerek yok. Tkinter bize bu tür işleri yapabilmemiz için bize bazı araçlar sunar. İşte biz de bu bölümde Tkinter’in bize sunduğu bu araçları inceleyeceğiz...

7.1. Hata Mesajı Gösteren Pencere

Bu bölümde inceleyeceğimiz ilk penceremiz “hata mesajı gösteren pencere” olacaktır. Yalnız bahsettiğimiz bu pencereleri kullanabilmek için öncelikle “tkMessageBox” adlı modülü içe aktarmamız gerekiyor. Şöyle:

from Tkinter import *
from tkMessageBox import *

Tkinter’de kullanıcıya bilgi mesajı gösteren bütün pencereler tkMessageBox adlı modülün içinde yer alıyor. Dolayısıyla bu pencereleri kullanmak istediğimizde, Tkinter modülüyle birlikte tkMessageBox modülünü de içe aktarmayı unutmuyoruz.

Bir önceki bölümde hatırlarsanız, kullanıcıdan e.posta adresi girmesini istediğimiz ufak bir uygulama yazmıştık. Gelin isterseniz yine o örnek üzerinden gidelim. Öncelikle kodlarımızın ne olduğuna bakalım:

# -*- coding: utf-8 -*-
from Tkinter import *

pencere = Tk()

def kapat():
    if not entry.get():
        yenipen = Toplevel()

        uyari = Label(yenipen)
        uyari["text"] = "Lütfen geçerli bir e.posta adresi yazın!"
        uyari.pack()

        uybtn = Button(yenipen)
        uybtn["text"] = "Tamam"
        uybtn["command"] = yenipen.destroy
        uybtn.pack()

    else:
        pencere.destroy()

etiket = Label()
etiket["text"] = "e.posta adresiniz:"
etiket.pack()

entry = Entry()
entry.pack()

dgm = Button()
dgm["text"] = "Gönder"
dgm["command"] = kapat
dgm.pack()

pencere.mainloop()

Gördüğünüz gibi, aslında basit bir iş için çok fazla kod yazmışız. Gelin bu kodları, tkMessageBox modülünün de yardımıyla sadeleştirelim ve hatta güzelleştirelim:

# -*- coding: utf-8 -*-

from Tkinter import *
from tkMessageBox import *

pencere = Tk()

def kapat():
    if not entry.get():
        showerror("Hata!", "Lütfen geçerli bir e.posta adresi girin!")
    else:
        pencere.destroy()

etiket = Label()
etiket["text"] = "e.posta adresiniz:"
etiket.pack()

entry = Entry()
entry.pack()

dgm = Button()
dgm["text"] = "Gönder"
dgm["command"] = kapat
dgm.pack()

pencere.mainloop()

Ne kadar hoş, değil mi?? Bu şekilde hem daha az kod yazmış oluyoruz, hem de elde ettiğimiz çıktı daha oturmuş bir görünüme sahip. Dikkat ederseniz, hata mesajımız sevimli bir hata simgesi de içeriyor... Bu hata penceresinin bize sağladıklarını kendimiz yapmaya çalışırsak epey kod yazmamız gerekir. Dolayısıyla yazacağımız programlarda böyle bir imkanımızın olduğunu da göz önünde bulundurmamız bizim için faydalı olacaktır.

Bir hata penceresinin sahip olması gereken bütün özellikleri taşıyan bu hata penceresini şu tek satırlık kod yardımıyla oluşturduk:

showerror("Hata!", "Lütfen geçerli bir e.posta adresi girin!")

Burada neyin ne olduğu belli. Ama isterseniz bu satırı biraz inceleyelim:

Gördüğünüz gibi aslında kullandığımız şey “showerror()” adlı bir fonksiyon... Bu fonksiyonu iki parametreli olarak kullandık. showerror() fonksiyonu içinde kullandığımız ilk parametre “Hata” adlı bir karakter dizisi. Bu ifade, oluşacak hata penceresinin başlığı olacak... İkinci parametremiz olan “Lütfen geçerli bir e.posta adresi girin!” adlı karakter dizisi ise hata penceremizin gövdesi, yani kullanıcıya göstereceğimiz mesajın ta kendisidir.

Burada kullandığımız showerror() fonksiyonu başka bir parametre daha alabilir. Bu parametrenin adı “detail”dir. Bu parametreyi şöyle kullanıyoruz:

showerror(“Hata!”, “Lütfen geçerli bir e.posta adresi girin!”, detail = “e.posta adresi uydurma olmasın!”)

“detail” parametresi, varsa hatayla ilgili ayrıntıları da kullanıcıya göstermemizi sağlıyor. Bu arada yukarıdaki örnek kod satırı eğer gözünüze uzun görünüyorsa bu satırı şu şekilde bölebilirsiniz:

showerror("Hata!",
          "Lütfen geçerli bir e.posta adresi girin!",
          detail = "e.posta adresi uydurma olmasın!")

Özellikle Python kodlarına duyarlı bir metin düzenleyici kullanıyorsanız, (mesela IDLE) virgülden sonra enter tuşuna bastığınızda metin düzenleyiciniz satırları uygun şekilde hizalayacaktır...

Elbette isterseniz daha estetik bir görüntü elde etmek için değişkenlerden de faydalanabilirsiniz:

baslik = "Hata!"
mesaj = "Lütfen geçerli bir e.posta adresi girin!"
detay = "e.posta adres uydurma olmasın!"

showerror(baslik, mesaj, detail = detay)

“detail” parametresi dışında, showerror() fonksiyonu için (ve tabii öteki bilgi mesajları için) kullanabileceğimiz başka parametreler de vardır. Mesela bu parametrelerden biri “type” parametresidir. Bu parametre ile, bilgi ekranında gösterilecek düğmelerin tipini belirleyebiliriz. Bu parametre ile birlikte kullanabileceğimiz altı farklı seçenek vardır:

ABORTRETRYIGNORE:
Pencere üzerinde “vazgeç”, “tekrar dene”, “yoksay” düğmelerini gösterir.
OK:
Pencere üzerinde “tamam” düğmesi gösterir.
OKCANCEL:
Pencere üzerinde “tamam” ve “iptal” düğmelerini gösterir.
RETRYCANCEL:
Pencere üzerinde “yeniden dene” ve “iptal” düğmelerini gösterir.
YESNO:
Pencere üzerinde “evet” ve “hayır” düğmelerini gösterir.
YESNOCANCEL:
Pencere üzerinde “evet”, “hayır” ve “iptal” düğmelerini gösterir.

Bu seçenekler şöyle kullanılır:

showerror(baslik, mesaj, detail=detay, type=ABORTRETRYIGNORE)

Burada “ABORTRETRYIGNORE” yerine başka herhangi bir seçeneği de koyabilirsiniz elbette...

Başka bir parametre ise “default” parametresidir. Bu parametre yardımıyla, hata penceresi ilk açıldığında hangi düğmenin seçili (etkin) olacağını belirleyebiliriz. Yani doğrudan enter tuşuna basıldığında hangi düğmenin çalışacağını bu “default” adlı parametre ile belirliyoruz.

“default” parametresi yedi farklı seçeneğe sahiptir:

  • ABORT
  • RETRY
  • IGNORE
  • OK
  • CANCEL
  • YES
  • NO

Bu parametreyi de şöyle kullanıyoruz:

showerror(baslik, mesaj, detail=detay, type=ABORTRETRYIGNORE, default=RETRY)

En son parametremiz ise “icon” adlı olan... Bu parametre yardımıyla, bilgi penceresi üzerinde gördüğümüz simgenin türünü belirleyebiliriz. Bu parametre ile şu seçenekleri kullanabiliriz:

  • ERROR (Hata simgesi)
  • INFO (Bilgi simgesi)
  • QUESTION (Soru simgesi)
  • WARNING (Uyarı simgesi)

Bu parametreyi ise şöyle kullanacağız:

showerror(baslik, mesaj, detail=detay, type=ABORTRETRYIGNORE, default=RETRY, icon=WARNING)

Bu arada, mümkün olan yerlerde kod satırlarımızı yukarıda gibi uzun tutmamak iyi bir yaklaşım olacaktır. Dolayısıyla yukarıdaki uzun satırı şu şekle getirmek okunaklılığı artırır:

showerror(baslik,
          mesaj,
          detail = detay,
          type = ABORTRETRYIGNORE,
          default=RETRY,
          icon=WARNING)

Peki kullanıcı bu bilgi ekranındaki herhangi bir düğmeye bastığında hangi işlemin yapılacağını nasıl belirleyeceğiz? Yani mesela diyelim ki kullanıcı “OK” tuşuna bastı, işte böyle bir durumda hangi işlemin yapılması gerektiğini nasıl bulacağız? Bu işi yapmak oldukça basittir. Hemen şöyle bir örnek verelim:

#-*-coding:utf-8-*-

from Tkinter import *
from tkMessageBox import *

pencere = Tk()

def soru():
    cevap = showerror("Uyarı",
                      "Bu işlem diskteki bütün verileri silecektir.",
                      type=OKCANCEL)

    if cevap == "ok":
        etiket["text"] = "disk biçimlendirildi!"

    if cevap == "cancel":
        etiket["text"] = "işlem durduruldu!"

etiket = Label(text="işlem durumu: ")
etiket.pack()

dgm = Button(text="diski biçimlendir!", command=soru)
dgm.pack()

mainloop()

Gördüğünüz gibi, showerror() fonksiyonunu bir değişkene atadık. Burada, “type” parametresini kullanarak, içinde “OK” ve “CANCEL” gibi iki farklı düğme barındıran bir bilgi ekranı oluşturduğumuza dikkat edin. Eğer kullanıcı “OK” tuşuna basarsa “cevap” değişkeninin değeri “ok”, yok eğer kullanıcı “CANCEL” tuşuna basarsa cevap değişkeninin değeri “cancel” olacaktır. İşte bu değerleri birer “if” deyimine bağlayarak her bir düğmeye ayrı bir işlev atayabiliriz...

Burada kendi kendinize, type parametresine farklı değerler vererek denemeler yapmanızı tavsiye ederim. Mesela OKCANCEL, RETRYCANCEL, ABORTRETRYIGNORE gibi değerlerin ne tür çıktılar verdiğini kontrol ederek çıktıya göre farklı fonksiyonlar yazabilirsiniz... Mesela şöyle bir test uygulaması ile her bir düğmenin nasıl bir çıktı verdiğini kontrol edebilirsiniz:

from Tkinter import *
from tkMessageBox import *

pencere = Tk()

def soru():
    cevap = showerror("Uyarı",
                      "Bu işlem diskteki bütün verileri silecektir.",
                      type=ABORTRETRYIGNORE)
    print cevap

dgm = Button(text="diski biçimlendir!", command=soru)
dgm.pack()

mainloop()

Elbette burada çıktıları konsola veriyoruz. Ama eğer siz isterseniz arayüz üzerindeki “Label()” aracının “text” seçeneğine de bu çıktıları yazdırabilirsiniz:

from Tkinter import *
from tkMessageBox import *

pencere = Tk()

def soru():
    cevap = showerror("Uyarı",
                      "Bu işlem diskteki bütün verileri silecektir.",
                      type=ABORTRETRYIGNORE)

    etiket["text"] = cevap

etiket = Label()
etiket.pack()

dgm = Button(text="diski biçimlendir!", command=soru)
dgm.pack()

mainloop()

Gördüğünüz gibi, showerror() fonksiyonunu kullanmak zor değil. Gelin isterseniz şimdi öteki bilgi pencerelerine de şöyle bir göz atalım...

7.2. Bilgi Mesajı Gösteren Pencere

Bir önceki bölümde hata mesajı gösteren pencereyi işlemiştik. Bu bölümde ise “bilgi mesajı gösteren pencere”yi öğreneceğiz.

Bilgi mesajı gösterne pencere de tıpkı hata mesajı gösteren pencere gibidir. Bu kez showerror() fonksiyonu yerine “showinfo()” fonksiyonunu kullanacağız. En basit şekliyle showinfo() fonksiyonu şöyle kullanılır:

showinfo(“Bilgi”, “İşlem başarıyla tamamlandı!”)

Gelin isterseniz bu fonksiyonu kapsamlı bir örnek içinde inceleyelim:

# -*- coding: utf-8 -*-

from Tkinter import *
from tkMessageBox import *

pencere = Tk()

def kapat():
    if not entry.get():
        showerror("Hata!", "Ürün sayısı belirtmediniz!")
        return "break"
    try:
        int(entry.get())
        showinfo("Bilgi", "%s ürün sepete eklendi!"%entry.get())

    except ValueError:
        showerror("Hata!", "Lütfen bir sayı girin!")


etiket = Label()
etiket["text"] = "ürün adedi:"
etiket.pack()

entry = Entry()
entry.pack()

dgm = Button()
dgm["text"] = "Gönder"
dgm["command"] = kapat
dgm.pack()

pencere.mainloop()

Burada birkaç işlemi aynı anda yaptık. Programımızın amacı, kullanıcının kutucuğa bir sayı yazmasını sağlamak. Ayrıca kullanıcının, kutucuğa hiç bir şey yazmadan “Gönder” tuşuna basabileceğini de hesaba katmamız gerekir... Böyle bir duruma karşı, kodlarımız içinde şu satırları yazdık:

if not entry.get():
    showerror("Hata!", "Ürün sayısı belirtmediniz!")
    return "break"

Eğer kullanıcımız, kutucuğu boş bırakırsa kendisine bir hata mesajı gösteriyoruz. Burada return “break” ifadesini kullanmamızın nedeni, hata mesajı gösterildikten sonra programın çalışmaya devam etmesini engellemek. Eğer bu ifadeyi yazmazsak, programımız kullanıcıya hata mesajı gösterdikten sonra alt satırdaki kodları da işletmeye devam edecektir... İsterseniz o satırı kaldırıp kendi kendinize birtakım denemeler yapabilirsiniz...

Bildiğimiz gibi, entry.get() metodundan elde edilen verinin tipi karakter dizisidir. Kullanıcının bir sayı mı yoksa bir harf mi girdiğini tespit edebilmek için öncelikle, kutucuğa kullanıcı tarafından yazılan değerin sayıya dönüştürülebilen bir veri olup olmadığına bakıyoruz. Bunun için şu kodları yazdık:

try:
    int(entry.get())
    showinfo("Bilgi", "%s ürün sepete eklendi!"%entry.get())

except ValueError:
    showerror("Hata!", "Lütfen bir sayı girin!")

Burada eğer kullanıcının yazdığı şey sayıya dönüştürülebilen bir veri ise kendisine “showinfo()” fonksiyonunu kullanarak kaç ürünün sepete eklendiği bilgisini veriyoruz. Ama eğer mesela kullanıcı sayı girmek yerine “fsdfd” gibi bir şey yazarsa, bu defa “showerror()” fonksiyonunu kullanarak ona, sayı girmediğine dair bir hata mesajı gösteriyoruz. Burada “try except” bloklarını nasıl kullandığımıza dikkat edin...

Gördüğünüz gibi, showinfo() fonksiyonunun kullanımı showerror() fonksiyonunun kullanımına çok benziyor. Hatta hemen hemen aynı bile diyebiliriz...

Geçen bölümde showerror() fonksiyonunu işlerken, bu fonksiyonun birtakım parametreler de alabildiğini söylemiştik. Orada söylediklerimiz showinfo() fonksiyonu için de geçerlidir. Mesela burada da “detail” parametresini kullanarak, kullanıcıya konuyla ilgili ek bilgi verebiliriz:

showinfo("Bilgi", "%s ürün sepete eklendi!"%entry.get(),
         detail="Ama bence bu kadar ürün az!\nÜrünlerimizden biraz daha alın!")

showerror() ile showinfo() arasındaki benzerlikler bununla da sınırlı değildir. Mesela geçen bölümde öğrendiğimiz “type” parametresini burada da kullanabiliriz:

showinfo("Bilgi", "%s ürün sepete eklendi!"%entry.get(),
         detail="Ama bence bu kadar ürün az!\nÜrünlerimizden biraz daha alın!",
         type=OKCANCEL)

Gördüğünüz gibi, showerror() konusunda ne öğrendiysek burada da uygulayabiliyoruz. İsterseniz geçen bölümde öğrendiğimiz bilgileri showinfo() fonksiyonuna da uygulayarak kendi kendinize el alıştırmaları yapabilirsiniz...

Sıra geldi başka bir bilgi mesajı penceresini incelemeye...

7.3. Uyarı Mesajı Gösteren Pencere

Bu bölümde kullanıcılarımıza bir uyarı mesajı gösteren pencerenin nasıl oluşturulacağına bakacağız... Burada da yeni bir fonksiyonla karşılaşacağız. Ama endişelenmeye gerek yok. Bu fonksiyon da tıpkı showerror() ve showinfo() fonksiyonlarına benzer. Adı ve tabii ki üzerindeki ünlem simgesi dışında her yönüyle onlarla aynıdır. Bu fonksiyonumuzun adı showwarning(). İsterseniz bununla ilgili de basit bir örnek yapıp bu konuyu kapatalım:

# -*- coding: utf-8 -*-

from Tkinter import *
from tkMessageBox import *

pencere = Tk()

def kapat():
      showwarning("Bağlantı yok!", "İşleminizi gerçekleştiremiyorum!")

etiket = Label()
etiket["text"] = "ürün adedi:"
etiket.pack()

entry = Entry()
entry.pack()

dgm = Button()
dgm["text"] = "Gönder"
dgm["command"] = kapat
dgm.pack()

pencere.mainloop()