5. Olaylar ve Popup¶
Türkçe’de “Ortaya çıkan, oluşan durum” olarak tanımladığımız olay (event), Kivy için de geçerlidir. Örneğin “düğmeye bastırmak”, “bastırılmayı bırakmak”, “seçim yapmak”, “bir tuşa basmak” gibi birçok durum birer Kivy olayıdır. Bu olaylar gerçekleştiğinde, programımızın bir tepki vermesi gerekir. Bir olay gerçekleştiğinde verilecek tepki bir işlev (fonksiyon) tarafından gerçekleştirilebilir. Olay gerçekleştiğinde ilgili fonksiyonun çağrılabilmesi için, fonksiyonu olaya bağlamak gerekmektedir.
Önce bir düğmeye bastırıldığında üzeirndeki metnin değişmesini sağlayacak bir
program yazmaya çalışalım. Bu programı öncelikle Python kodu yazarak öğreneceğiz, daha sonra kvlang
ile nasıl
gerçekleştirilebileceğine bakacağız. Programımız Liste 5.1‘de görülmektedir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class olayUyg(App):
def metni_degistir(self, nesne):
self.dugme.text='Tıkladın ve değiştim.'
def build(self):
duzen=BoxLayout()
self.dugme=Button(text='Değiştir')
self.dugme.bind(on_press=self.metni_degistir)
duzen.add_widget(self.dugme)
return duzen
olayUyg().run()
|
Liste 5.1‘deki programı çalıştırdığımızda tüm ekranı kaplayan bir düğme görünecektir. Düğmenin üzerinde
“Değiştir” metni görünmektedir. Bu düğmeyi self
‘in bir özelliği yapmamaızın nedeni, sınıf içerisindeki tüm işlevlerden
erişebilmektir. Bu düğmeye bastırıldığında çağrılacak olan işlevi, düğmeinin bind()
özelliği
ile bağlıyoruz. Bir olayı bir nesneye bağlamak için bind()
özelliğini kullanırız. Bu işleve, hangi olayı
bağlamak istiyorsak, onu parametre ve bu parametreye de çağrılacak olan işlevi yazıyoruz. 15. satırda
bind()
işlevine on_press parametrisini (bu düğmeye bastırılma olayını ifade eder) ve değer olarak ta
self.metni_degistir
işlevini atadık. Böylelikle düğmeye bastırıldığında self.metni_degistir
işlevi çağrılacaktır.
Çağrılan işleve nesnenin kendisi (burada self.dugme
‘dir) argüman olarak gönderilir. Aslında dugme
‘yi self
‘in
özelliği yapmadan, gelen nesne üzerinden de metni değiştirebilirdik:
nesne.text='Tıkladın ve değiştim.'
aynı görevi görürdü. Şimdi aynı programı kv lang
ile yazalım. Programımızı Liste 5.2‘da görüyorsunuz.
1 2 3 4 5 6 7 8 9 10 | # -*- coding: utf-8 -*-
from kivy.app import App
class olayUyg(App):
def metni_degistir(self):
self.root.ids.dugme.text='Tıkladın ve değiştim.'
olayUyg().run()
|
İlgili kv
dosyasını Liste 5.3‘da görüyorsunuz.
1 2 3 4 5 6 7 | BoxLayout:
Button:
id: dugme
text: 'Değiştir'
on_press: app.metni_degistir()
|
Şimdi biraz program ve kv
dosyası üzerinde konuşalım. kv
dilinde garfik parçacıklarına isimleri id
özelliği
ile veriyoruz. 3. satırdaki id: dugme
yapmamızın nedeni bu garfik parçacığına (nesneye) program içerisinden ulaşmak için kullanacağımızdır.
Bu düğmeye bastırıldığında çağrılacak olan işlevi app
‘ın bir özelliği ile veriyoruz. Çağrılan uygulamanın tüm nesneleri,
kv
dili içerisinden app
‘ın özelliği ile erişilir. Liste 5.2 programına bakacak olursak, kv
dili
içerisinde tanımlanmış grafik parçacıklarına erişmek için self.root.ids
‘nin bir özelliği ile eriştiğimizi anlarsınız. kv
‘deki
bir nesneye erişmek için o nesnenin id
ile verilmiş ismini kullanıyoruz.
Kullanıcının metin gireceği bir metin kutusu, altında bir etiket ve onun altında da bir düğme bulunan bir program yazalım. Bu programı yazmadaki amacımız, metin kutusuna girilen değeri etikette görüntülemktir. Programımızı Liste 5.4‘da görüyorsunuz.
1 2 3 4 5 6 7 8 9 | from kivy.app import App
class olayUyg(App):
def metni_degistir(self):
girilen_metin = self.root.ids.metin_girdisi.text
self.root.ids.etiket.text='Merhaba %s !' % girilen_metin
olayUyg().run()
|
Bu programla kullanacağımız kv
dosyasını da Liste 5.5‘da görüyorsunuz.
1 2 3 4 5 6 7 8 9 10 11 12 | BoxLayout:
orientation: 'vertical'
TextInput:
id: metin_girdisi
Label:
text: 'Adınızı yukarıya yazın...'
id: etiket
markup: True
Button:
id: dugme
text: 'Değiştir'
on_press: app.metni_degistir()
|
kv
dosyasında etiket için neden markup: True
dediğimizi sonra açaıklayacağız. Programımızı çalıştıralım ve
üstteki metin kutusuna adımızı yazalım. “Değiştir” düğmesine tıkladığımızda, metin kutusundaki isim etiket üzerine yazılacaktır.
Programın çalışmış halini Şekil 5.1 ‘de görüyorsunuz.
5.1. İşaret Dili (markup)¶
Etiket ve düğmelerde renklerin kullanımı çok kolay. Liste 5.5‘deki kv
dosyasının 8. satırında markup: True
bulunmaktadır. Bunun anlamı bu etiket metni için işaret dilinin (markup) kullanılacağıdır. Eğer program içerisinde
bir etiket tanımlamış olsaydık, işaret dilini etkinleştirmek için
etiket = Label(markup=True)
diyebilirdik. Ya da daha önceden tanımlanmış bir etiket
nesnesi için:
etiket.markup=True
şeklinde aktifleştirebilirdik. Keşke Kivy tıpkı Qt gibi standart html’yi desteklemiş olsa idi, ancak ne yazıkki standart html yerine kendi içerisinde birtakım işaretler vardır. Önce Liste 5.2‘deki programda kullanıcının adını etikete yazarken kırmızı reknte yazmayı deneyelim. Bunun için 7. satırı aşağıdaki gibi değiştirin:
self.root.ids.etiket.text='Merhaba [color=#FF0000] %s [/color] !' % girilen_metin
Artık isim kırmızı renkli olacaktır. Burada anlaşılacağı gibi Kivy işaretleri [işaret] ile başlamakta ve [/işaret] ile bitirlmektedir. Sonucu Şekil 5.2 ‘de görüyorsunuz.
Kullanabileceğimiz diğer işaretler şöyle:
- [b][/b]
- Kalın metin
- [i][/i]
- İtalik metin
- [u][/u]
- Altı çizili metin
- [s][/s]
- Üstü çizili metin
- [font=<str>][/font]
- Yazıtıpi belirtimi. Örneğin
[font=DejaVuSerif.ttf]Merhaba Kivy![/font]
- [size=<integer>][/size]
- Yazıtıpi boyutunu belirtir
- [color=#<color>][/color]
- Yazı rengini değiştirir
- [ref=<str>][/ref]
- Metne bir link (bağ) konulur. Bu bağa tıklandığında “ref” de verilen değer, işleve gönderilir.
- [sub][/sub]
- Alt simge olarak gösterilir
- [sup][/sup]
- Üst simge olarak gösterilir
Basit bir diğer örnek olarak ref
‘i kullanalım. Liste 5.6‘deki programda etiket üzerindeki metne
tıklandığında ekrana (komut satırına) Selam Melike !
yazacaktır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.label import Label
class olayUyg(App):
def yazdir(self, nesne, deger):
print deger
#nesne.text = deger
def build(self):
etiket = Label(text='[ref=Selam Melike !] Merhaba Fatih ![/ref]')
etiket.markup=True
etiket.bind(on_ref_press=self.yazdir)
return etiket
olayUyg().run()
|
Eğer yazdir()
işlevini şu şekilde değiştirecek olursanız:
nesne.text = deger
Bu durumda, etiketteki “Merhaba Fatih !” metine tıkladığınızda, bu metin yerine “Merhaba Melike !” görünecektir.
5.2. Popup Pencere: (popup)¶
Bir programcının başı sıkıştığında hemen bir Popup pencereye başvurur. Kivy’de bu işlem oldukça basit. Önce program kodu ile nasıl yapılacağına bakalım. Liste 5.7‘deki programı inceleyin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.button import Button
class olayUyg(App):
def popAc(self, nesne):
icerik=Label(text='İşte bir popup')
popup = Popup(title='Popup Pencere Başlığı',
content=icerik,
size_hint=(None, None), size=(200, 200))
icerik.bind(on_touch_down=popup.dismiss)
popup.open()
def build(self):
return Button(text="Popup için tıkla", on_press=self.popAc)
olayUyg().run()
|
Bu programın ana düzeni bir tane düğmeden oluşmaktadır. Bu düğmeye tıklandığında self.popAc()
işlevi çağrılmaktadır.
Popup penceremiz bu işlevde açılmaktadır. Öncelikle açılacak pencerenin içeriğini hazırlamak gerek. Bu içerikte sadece
bir etiket bulunmaktadır. Siz istediğiniz bir pencere düzeni kullanarak içeriği istediğiniz gibi oluşturabilirsiniz. Bu içerik popup
nesnesinin content
parametresine verilmiştir. Genelde 17. satırda bulunan bind(on_touch_down=popup.dismiss)
bağlantısını genellikle yapmayız. Biz burada tam bir örnek olsun diye verdik.
on_touch_down olayı bir grafik parçacığına dokunulduğunu ifade eden olaydır. Burada Popup penceresindeki
içeriğe dokunulduğunda pencerenin kapanmasını sağlayan dismiss işlevi aktifleştirilmiştir. Bu programda (200,200)
boyutlarında bir Popup penceresi açılır. Normalde Popup penceresinin dışındaki bir alana dokunulduğunda Popup kapanır.
Eğer otomatik olarak kapanmasını istemiyorsanız auto_dismiss parametresinin değerini False
yapmalısınız. Yani
auto_dismiss=False
kullanmalısınız.
kv
dili ile bir Popup oluştruracağız. Biraz daha karmaşık bir program oluşturalım. Ana penceremizde bir etiket olsun,
etiketin altında bir düğme ve bu düğmeye bastırılınca bir Popup açılsın. Bu Popup biraz daha farklı olsun, sanki ModalView gibi
davransın. Açılan Popup penceresine bir metin kutusu ve hemen yanına bir düğme ekleyelim. Popup dışarı bir yere tıklanınca
kapanmasın. Üzerindeki düğmeye bastırılınca önce yapacağı işi yapsın sonra da kapansın. Önce kv
dosyasından başlayalım.
Daha önce bir kv
dosyasında sadece ana pencereyi tanımlamıştık, oysaki bir programda birden çok pencere olabilir ve bunların
hepsi bir kv
dosyasında tanımlanabilir. Eğer birden fazla pencere tanımlanacaksa, programda (bize main.py
) her pencereya ait
bir sınıf tanımlanmadır. Bu sınıfa ait pencere düzeni kv
dosyasında <sınıfAdı>: ile belirtilir. ‘deki kv
Liste 5.8‘dosyasını inceleyin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <olayUyg>:
BoxLayout:
orientation: "vertical"
Label:
id: ana_pencere_etiket
markup: True
text: "Aşağıdaki düğmeye tıklarsan [b][i]Popup[/i][/b] pencere açılır."
size_hint_y: 3
Button:
text: "Popup Açma Düğmesi"
on_press: app.popAc()
size_hint_y: 1
<PopUpPencere>:
size_hint: (None, None)
size: (300, 100)
auto_dismiss: False
title: "Adınız:"
#on_touch_down: self.dismiss()
BoxLayout:
TextInput:
id: girilen_ad
size_hint_x: 3
Button:
text: "Tamam"
size_hint_x: 1
on_press: app.popup.olayDugme(app)
|
Burada <olayUyg>
daha önceden da kullandığımız, ana sınıfımızın (olayUyg()
) penceresini oluşturmak için kullanılacaktır.
<PopUpPencere>
bloğundaki tanımlar ise, programımızda PopUpPencere()
isimli bir sınıf tanımlanacak ve o sınıfın pencere
düzenini oluşturacaktır. Dikkat etmiş iseniz, ana sınıfımıza ait grafi parçacıkların kodları en soldan başlamaktadır,
diğer bir deyişle (<olayUyg>:
) ile aynı hizada başlıyor. Hemen altında BoxLayout:
düzeni tanımlanıyor. Diğer sınıflara ait
pencere düzenlerini tanımlarken ise <sınıfAdı>: en soldan, bunun altındaki kodlar bir içerden tanımlanıyor. Aslında ana pencereye ait
kodlar tanımlanırken <anaSinifAdı>: yazmaya da gerek yoktur. Ancak kod okunurluğu açısından bu satırı ekliyoruz.
Buna göre Liste 5.8‘deki ilk satır yazılmasa da düzgün çalışır.
Dosya yapısından sonra birazda kodlardan konuşalım. Ana sınıfın penceresin oluşturan <olayUyg>
bloğunda bir kutu düzeni oluşturuluyor.
Bu bir etiket (size_hint_y: 3
ile pencerenin %75’ini kaplar), altında bir düğme oluşturuluyor. Bu düğme tüm yüksekliğin %25’ini
kaplamaktadır. Düğmeye bastırıldığında uygulamadaki (diğer bir deyişle programımızda tanımlı ana sınıfımız olan olayUyg()
)
popAc()
işlevi çağrılıyor. kv
dosyalarında ana sınıftaki tüm nesnelere ap
‘ın bir özelliği olarak erişilebileceğini tekrar
hatırlatalım. İkinci penceremiz (<PopUpPencere>
) açılacak olan Popup’ın düzenini oluşturmak için kullanılacaktır. Buradan
programda bu düzeni kullanacak olan sınıfın PopUpPencere()
olacağını anlıyoruz. İlk defa bir pencerenin piksel olarak
büyüklüğünü nasıl belirleyebileceğimizi görüyoruz. Bunu size ile yapıyoruz. Eğer bir grafik parçacığında size
parametresini
kullanırsanız, size_hint
‘i mutlaka None
yapmalısınız. size
parametresine bir tüp atanır ve bu tüp grafik parçacığının
piksel olarak (eni, boyu) şeklindedir. Burada eni 300, boyu 100 piksel olan bir pencere açılacaktır. Daha önce oralnları
size_hint_x
ve size_hint_y
olarak vermiştik. İkisini bir arada vermek için size_hint kullanabilirsiniz. Yine
bu parametre bir tüp alır ve (en_oranı, boy_oranı) şeklindedir. Popup pencerenin dışında bir yere tıklandığında kapanmasını
önlemek için auto_dismiss: False
satırını kullandık. Gelelim düğmeye: düğmeye bastırıldığında on_press
uygulamanın
bir özelliğine erişebilmektedir. Bu özelliği ap
‘dan alabiliyoruz. Fakat düğmeye bastırıldığında, düğmeye ait sınıftaki
bir işlevi çağırmak istiyoruz. Bu durumda, düğmenin sınıfını (PopUpPencere()
) na sınıfın bir özelliğ yaparsak, o zaman düğme sınıfındaki
nesnelere ap
‘ı kullanarak erişebiliriz. İşte bu anlattıklarımız programımızın (numref:olaylar_main6) 14. satırında:
self.popup=PopUpPencere()
şeklinde yazarak PopUpPencere()
sınıfını ana sınıfın bir özelliği haline getiriyoruz. Bir sınıfta bir nesneyi self
‘in
özelliği yaparsanız, bu özellik o sınıfınızın bir özelliği olur ve o sınıf içerisinden her yerden erişilebilir. Böylelikle `
PopUpPencere()
sınıfına ait özelliklere, ana sınıf içerisinden self.popup
‘ın bir özelliği olarak erişilebilir. kv
dosyasında
ana sınıf app
olarak erişiliyordu, bu durumda app.popup
nesnesi PopUpPencere()
sınıfını temsil edecektir.
Eğer PopUpPencere()
sınıfının içerisinden ana sınıfımıza ait özelliklere erişmek istyorsak, PopUpPencere()
‘da çağırdığımız
işlevlere ana sınıfın kendisini argüman olarak göndermemiz gerekir. Eğer program kodundan çağırıyorsak self
‘i, kv
dosyasında
çağırıyorsak ap
‘ı argüman olarak göndermeliyiz. Elbette işlevde bu argümanı alacak bir parametre bulunmalıdır.
Liste 5.8‘dosyasında Popup penceredeki düğmeye bastırıldığında app.popup.olayDugme(app)
işlevini çağırdık.
PopUpPencere()
sınıfında tanımlanacak olayDugme()
işlevi app
‘ı alacaktır.
Bunu Liste 5.9‘deki 6. satırda görüyorsunuz.
Liste 5.8 kv
dosyasını kullanacak olan programımız Liste 5.9‘da yazılmştır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from kivy.app import App
from kivy.uix.popup import Popup
class PopUpPencere(Popup):
def olayDugme(self, uyg):
ad=self.ids.girilen_ad.text
uyg.root.ids.ana_pencere_etiket.text="Merhaba %s !" % ad
self.dismiss()
class olayUyg(App):
def popAc(self):
self.popup=PopUpPencere()
self.popup.open()
olayUyg().run()
|
Bu programda olayDugme()
işevi ana penceredeki etikete erişiyor ve Popup’da girilen ismi ana pencerenin etiketine yazıyor.
kv
dosyasındaki on_press: app.popup.olayDugme(app)
satırı, ana sınıfı (app
) bu işeleve gönderiyor, bu işlevin uyg
parametresine atanıyor. Böylelikle uyg.root.ids
kullanılarak ana penceredeki tanımlanmış grafik parçacıklarına erişebiliyoruz.
Programımızı çalıştırıp alttaki düğmeye bastırdığımızda elde edeceğimiz görüntü Şekil 5.3‘deki gibi olacaktır.
Adımızı yazıp “Tamam” düğmesine bastırdığımızda Popup kapanacak ve Şekil 5.4‘deki gibi olacaktır.
Artık basit bir uygulama yazabiliriz. Şu can sıkıcı ve hiçbir işe yaramayan Metin Düzenleyici yazacak kadar bilgi sahibi olduk.