Kivy Mobil Programlama

Transkript

Kivy Mobil Programlama
Kivy Mobil Programlama
Sürüm 0.1
Mustafa Başer
12 August 2016
İçindekiler
1
Giriş
1.1
1.2
1.3
1.4
.
.
.
.
3
3
3
4
4
2
Kivy’nin Kurulumu
2.1 Windows’da Kurulum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Linux’da Kurulum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
6
3
Temel Bilgiler
3.1 Merhaba Dünya . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Pencere Düzenleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
8
4
Kivy Dili: kv (kv lang)
4.1 “Merhaba Dünya” yeniden . . . . . .
4.2 Kutu Pencere Düzeni (Box Layout) .
4.3 Izgara Pencere Düzeni (Grid Layout)
4.4 Parçacık Boyutları (size_hint) . . . .
4.5 İkisi Bir Arada . . . . . . . . . . . .
Kivy Hakkında .
Belge Hakkında
Ne Bilmeliyim?
UYARI . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
15
16
17
18
19
5
Olaylar ve Popup
5.1 İşaret Dili (markup) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Popup Pencere: (popup) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
23
25
6
Metin Düzenleyici
6.1 Ana Pencere . .
6.2 Farklı Kaydet . .
6.3 Kaydet . . . . .
6.4 Aç . . . . . . .
6.5 Yeni . . . . . . .
6.6 Çıkmadan Önce
7
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
31
31
32
38
39
42
44
Paketleme
7.1 Buildozer Kurulumu
7.2 Paket Derleme . . .
7.3 İmzalama . . . . . .
7.4 Sanal Linux Makina
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
47
48
49
52
.
.
.
.
.
.
i
8
9
Atlıkarınca ve Resim Gösterici
8.1 Atlıkarınca (Carousel) . . . .
8.2 Resim Gösterici . . . . . . .
8.3 Zamanlayıcı ve Slayt Gösterisi
8.4 Kronometre Uygulaması . . .
.
.
.
.
59
59
60
66
68
Liste Görünümü ve Eylem Çubuğu
9.1 Liste Görünümü . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.2 Açılır Kutu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.3 Eylem Çubuğu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
71
86
94
10 Dizinler ve Tablolar
ii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
107
Kivy Mobil Programlama, Sürüm 0.1
İçindekiler:
İçindekiler
1
Kivy Mobil Programlama, Sürüm 0.1
2
İçindekiler
BÖLÜM 1
Giriş
Bu belge Kivy ile mobil programlamayı öğretmek amacı ile hazırlanmıştır.
1.1 Kivy Hakkında
Kivy mobil cihazlarda da çalışabilecek programların yazılabileceği bir Python modülüdür. Diğer bir deyişle Mobil
GUI Toolkit (Mobil Grafik Kullanıcı Arayüzü Aracı) diyebiliriz. Python ile Mobil Uygulama geliştirmek isteyenlerin
çoğunluğu Kivy’i tercih etmektedir. Kivy ile yazacağınız programlar hemen her platformda çalışabilir. Bu platformları
şöyle sıralaybiliriz;
• Masaüstü Bilgisayarlar: Linux, Mac OS X, Windows
• Talbletler: Android cihaziar, iPad, iPhone
Kivy dokunmatik ekranlar için optimize edilmiş olmasına rağmen, geliştirilen uygulamalar masaüstü bilgisayarlarda
da rahatlıkla çalışabilmektedir. Bununla birlikte masaüstü bilgisayarlarda kullanılan diğer GUI araçlarındaki birçok
özelliği bulma şansınız yok.
Kivy aslında Pygame üzerine kurulmuş bir yapıdır. Tüm widgetler (grafik bileşenleri) Pygame ile çizilmektedir. Kivy
ile yazdığınız (aslında programı Python programa dili ile yazıyorsunuz) programlar, bir Linux makina (veya sanal
makinada çalışan bir Linux) ile kolaylıkla Android paketleri haline getirilebilmektedir. Getirilen paketler içerisinde
Python ve diğer bileşenler eklendiğinden, uygulama paketi kurulduğunda başka herhangi bir eklentiye gerek kalmadan
çalışmaktadır.
1.2 Belge Hakkında
Bu belge Mustafa Başer tarafından zaman buldukça hazırlanmaktadır ve sahibi © 2016, Mustafa Başer‘dir. Bu belge
GNU Özgür Belgeleme Lisansı ile dağıtılmaktadır.
1.2.1 Sürüm ve son değişiklik
Sürüm: 0.1
Son Değiştirme Tarihi: Fri Aug 12 07:45:56 2016
1.2.2 Belgeye katkıda bulunanlar
• Mustafa Başer
3
Kivy Mobil Programlama, Sürüm 0.1
Katkıda bulunmak için mbaser <at> mail.com adresine mail atabilirsiniz.
1.3 Ne Bilmeliyim?
Bu doküman sadece Kivy üzerinde yoğunlaşacaktır. Kivy ile program yazabilmek için Python bilmeniz gerekir. Python’u çeşitli web sitelerinden ya da bu dokümanın yazarı tarafından yazılmış Dikeyeksen yayınlarındaki Python kitabından öğrenebilirsiniz. Kitabın birinci kısmını öğrendiğiniz varsayılmıştır.
Bunun dışında komut satırına (Windows için cmd) aşina olmanız gerekmektedir. Böylelikle Paketleme bölümünde
anlatacağımız sanal makina üzerinde paketleme işini yapabilirsiniz.
1.4 UYARI
Bu belgede anlatılan içerik ve yayınlanan programlar ve kurulmu anlatılan programlmarın/paketlerin neden olabileceği
sorunlardan belgenin yazarı sorumlu tutulamaz.
4
Bölüm 1. Giriş
BÖLÜM 2
Kivy’nin Kurulumu
Bu belgede tüm çalışmalar Linux üzerinde yapılmaktadır, ancak okuyucuların bir kısmının Windows üzerinde çalışma
ihtimaline karşı Windows üzerinde kurulumda anlatılacaktır.
Bu belgenin hazırlanmaya başladığı zamanda, Paketleme bölümünde anlatacağımız Buildozer Python 2.7 ile hazırlandığı için Python 2.7 ile çalışılacaktır.
2.1 Windows’da Kurulum
Bu belgeyi okumaya başlamış iseniz, muhtemelen bilgisayarınızda Python kuruludur. Eğer kurulu değilse Python’un
İndirme Sayfası‘na giderek işletim sisteminize uygun olan 2.7 sürümünün son paketini indiriniz. Bu belge hazırlanırken 2.7.10 sürümü var idi. Belgenin üzerinde çalışıldığı Makinada 64 bitlik Windows 7 kurulu olduğundan şu paket
indirildi “Windows x86-64 MSI installer” (python-2.7.10.amd64.msi). İndirdiğiniz msi dosyası üzerine çift tıklayın,
eğer Windows’unuzun yönetici parolasını biliyorsanız, en iyisi tüm kullanıcılar için kurmaktır. Bunun için “Install for
all users” seçili iken “Next” düğmesine tıkladığınızda kurulacak olan patikanın C:\Python27\ olmasına özen gösterin. Birkaç tıklamadan sonra size yönetici parolası soarcaktır. Python 3.4 sürümü çalışabilir python.exe dosyasının
bulunduğu C:\Python27\ patikasını çevre değişkenine eklemez. Bunun için önce bir komut satırı açın (Başlat’a
tıklayın “Programları ve dosyaları ara” kutucuğuna cmd yazın ve klavyeden “Enter” tuşuna basın. Bu size siyah siyah
bir pencere açacaktır. Bu pencerede aşağıdaki komutu işletin:
=
{}=
{}@default
=0=1=2=0=1=2setx path \PYGZdq{}\PYGZpc{}path\PYGZpc{};C:\PYGZbs{}Python27\PYGZbs{}\PYGZdq{}
Artık Kivy’nin kurulumuna geçebiliriz. Bunun için komut satırında iken (siyah pencerede) aşağıdaki adımlarda belirtilen komutları çalıştırın:
1. pip ve wheel‘in son sürümünü yükleyelim:
=
{}=
{}@default
=0=1=2=0=1=2
python \PYGZhy{}m pip install \PYGZhy{}\PYGZhy{}upgrade pip wheel setuptools
2. Kivy için gerekli olan pakteleri kuralım (~100MB civarı dosya yüklenecektir biraz sabırlı olmalısınız):
=
{}=
{}@default
=0=1=2=0=1=2
python \PYGZhy{}m pip install docutils pygments pypiwin32 kivy.deps.sdl2 kivy.de
3. Ve son olarak Kivy’i kuralım:
5
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2
python \PYGZhy{}m pip install kivy
Kurulum bitti, artık kivy’i python içerisinden çağırabilirsiniz. Düzgün kurulup kurulmadığını Python komut satırından
aşağıdaki kodları çalıştırarak deneyebilirsiniz. Kurulum düzgün ise pencere başlığı “Bos Pencere” olan siyah ve boş
bir pencere açılacaktır.
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{i
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{App}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PYG{l+s+s2}{\P
2.2 Linux’da Kurulum
Değişik Linux dağıtımlarında kurulum birbirinden farklıdır. Burada sadece Debian Jessie’de (8.3) nasıl kurulacağını
anlatacağız. Tek yapmanız gereken:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZsh{}} apt\PYGZhy{}get install python\PYGZhy{}kivy
kurulumun doğru gerçekleştiğini yukarıda anlattığım gibi ile anlayabilirsiniz.
6
Bölüm 2. Kivy’nin Kurulumu
BÖLÜM 3
Temel Bilgiler
Bu bölümde Kivy’e giriş düzeyinde temel bilgiler verilecektir.
3.1 Merhaba Dünya
Hemen her programlma dilinde ilk yazılan program “Merhaba Dünya” cümlesinin yazılmasıdır. Bu belgede de bu
geleneği bozmayacağız ve Kivy’i öğrenmeye bununla başlayacağız. IDLE’e kullanarak aşağıdaki program kodunu
yazın ve merhabaDunya.py olarak kaydedin.
Liste 3.1: merhabaDunya.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k}{class} \PYG{n+nc}{ilkUygulama}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{return} \PYG{n}{Label}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+
\PYG{n}{ilkUygulama}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Programı çalıştırdığınızda Şekil 3.1‘deki gibi bir pencere açılacaktır.
Biraz bu program üzerinde konuşalım. Buraya kadar geldiğinize göre import satırlarını biliyor olmalısınız, bu nedenle burayı geçiyorum. Bütün Kivy programları bir ana sınıf tarafından yönetilir. Bu ana sınıf Kivy’deki App sınıfını
içerir. Bu programdaki ana sınıfımız ilkUygulama() dır. Ana sınıftaki build() işlevi mutlaka bir pencere düzeni
döndürür ve bu düzen program açıldığında kullanıcnın ilk gördüğü penceredir. Ana sınıf tarafından oluşturulan penecereye Ana Pencere diyoruz. Buradaki program çok basit olduğundan bir pencere düzeni döndürmek yerine sadece bir
etiket (Label) döndürmüştür, ve bu etiket Ana Pencere olarak karşımıza çıkmaktadır. Uygulamanın çalıştırılması, ana
sınıfın run() özelliği ile yapılır. Buradaki ilkUygulama().run() satırı uygulamamızın çalışmasını sağlar.
Eğer pencere ismi verilmemişse, pencerinin başlığında ana sınıfın ismi görünecektir. Pencere başlığını değiştirmek
için, title özelliğini kullanabiliriz. Sınıf tanımlanır tanımlanmaz hemen altında (def build(self): ile aynı hizada) aşağıdaki satırı ekleyerek yapabilirsiniz:
=
{}=
{}@default
7
Kivy Mobil Programlama, Sürüm 0.1
Şekil 3.1: Merhaba Dünya
=0=1=2=0=1=2\PYG{n}{title} \PYG{o}{=} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{Benim Kivy Programım}\PYG{l+
Bir diğer yöntem ise, build() işlevi altında return etmeden hemen önce şu satırı eklemektir:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{title} \PYG{o}{=} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}
Benzer şekilde pencere için kullanılacak olan simgeyi de icon özelliğini kullanarak yapabilirsiniz. Son durumda
build() işlevini şu şekilde yazabilirsiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{title} \PYG{o}{=} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{Be
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{icon} \PYG{o}{=} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{sim
\PYG{k}{return} \PYG{n}{Label}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+
simge.png dosyası, ya merhaba_dunya.py dosyasının kaydedildiği yerde olmalı ya da tam patika yazılmalıdır.
Örneğin resimler klasörüne koymuş iseniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{icon} \PYG{o}{=} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{
şeklinde yazılmalıdır.
3.2 Pencere Düzenleri
Bir pencereye birden fazla Grafik Parçacığı (widget) koyacaksanız, bir pencere düzeni oluşturmalısınız. Kivy programlarındaki pencere düzenleri iki şekilde oluşturulabilir:
• Pencere düzenleri kodlarıya
8
Bölüm 3. Temel Bilgiler
Kivy Mobil Programlama, Sürüm 0.1
• Kivy kv dili ile
3.2.1 Izgara Pencere Düzeni
Bu belge kapsamında kv dili kullanılacaktır. Ancak bir fikir vermesi açısından kodlayarak nasıl yapıldığını basit bir
örnek ile açıklamaya çalışalım. Şöyle bir pencereye ihtiyacımız olsun:
Bunun için altı adet grafik parçacığına (aslında pencere düzeni ile yedi) ihtiyacımız var. İki tanesi etiket (Label) iki
tanesi Metin Kutusu (TextInput) ve bir tanesi Düğme (index:Button). Bir tanede boş grafik parçacığı (Widget). Bu
programı Liste 3.2 gibi yazabiliriz.
Liste 3.2: girisFormu.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{n+nn}{kivy.uix.widget} \PYG{k+kn}{import} \PYG{n}{Widget}
\PYG{n+nn}{kivy.uix.gridlayout} \PYG{k+kn}{import} \PYG{n}{GridLayout}
\PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{n+nn}{kivy.uix.textinput} \PYG{k+kn}{import} \PYG{n}{TextInput}
\PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k}{class} \PYG{n+nc}{girisFormu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{duzen} \PYG{o}{=} \PYG{n}{GridLayout}\PYG{p}{(}\PYG{n}{cols}\PYG{o}{=}\PYG{l+m+mi}{2}
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{
\PYG{n}{kullanici\PYGZus{}adi} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{kullanici\PYGZus{}adi}\P
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{
\PYG{n}{parola} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{parola}\PYG{p}{)}
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Widget}\PYG{p}{(}\PYG{p}
\PYG{n}{gir\PYGZus{}dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{gir\PYGZus{}dugme}\PYG{p
3.2. Pencere Düzenleri
9
Kivy Mobil Programlama, Sürüm 0.1
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{title} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Gi
\PYG{k}{return} \PYG{n}{duzen}
\PYG{n}{girisFormu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Programımız şimdilik bir işe yaramamaktadır. Tek yaptığı bir giriş penceresi oluşturmak ve bunu kullanıcıya göstermektir. Düğmenin nasıl kullanılacağı, metin kutularındaki değerlerin nasıl alınacağı ileriki konularda anlatılacaktır.
Burada GridLayout ile ızgara pencere düzeni oluşturulmuştur. Bu sınıfa verilen cols=2 parametresi ızgaranın iki
sütundan oluşacağını söylemktedir. Kaç satırdan oluşuacağını belirtmiyoruz. Bir garfik parçacığına (burada ızgara
pencere düzeni) bir başka grafik parçacığını add_widget() ile ekliyoruz. Buradaki ızgaramız iki sütunlu olduğundan ızgara düzenine eklenen her iki parçacık bir satırda bulunur ve daha sonra yeni satıra geçilir. Şimdi size bir soru:
Sizce 24. satırı duzen.add_widget(Widget()) neden yazmışızdır?
Programımız çalıştığında Şekil 3.2 ‘deki gibi bir pencere açılacaktır.
Şekil 3.2: Giriş Formu
3.2.2 Kutu Pencere Düzeni
Benzer bir pencereyi kutu pencere düzeni ile oluşturalım. Kutu pencere düzeni BoxLayout parçacığı ile oluşturulur.
Liste 3.3 programını inceleyin.
Liste 3.3: girisFormu.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.widget} \PYG{k+kn}{import} \PYG{n}{Widget}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.textinput} \PYG{k+kn}{import} \PYG{n}{TextInput}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k}{class} \PYG{n+nc}{girisFormu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{duzen} \PYG{o}{=} \PYG{n}{BoxLayout}\PYG{p}{(}\PYG{n}{orientation}\PYG{o}{=}\PYG{l+s+
10
Bölüm 3. Temel Bilgiler
Kivy Mobil Programlama, Sürüm 0.1
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{
\PYG{n}{kullanici\PYGZus{}adi} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{kullanici\PYGZus{}adi}\P
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{
\PYG{n}{parola} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{parola}\PYG{p}{)}
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Widget}\PYG{p}{(}\PYG{p}
\PYG{n}{gir\PYGZus{}dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{gir\PYGZus{}dugme}\PYG{p
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{title} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Gi
\PYG{k}{return} \PYG{n}{duzen}
\PYG{n}{girisFormu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Programımız çalıştığında Şekil 3.3 ‘deki gibi bir pencere açılacaktır.
Şekil 3.3: Giriş Formu (Dikey Yönelimli)
Bu pencere bizim istediğimiz değil. Kutu pencere düzeninin ön tanımlı yönelimi yataydır. Yani eklenen parçacıklar yan yana görünür. Dikey olması için kutu pencere düzenini oluşturan BoxLayout() grafik parçacığına
orientation=’vertical’ paramteresini verdik. Dikey yönelimli bir kutu pencere düzeninde tüm parçacıklar
alt alta eklenir. Oysaki biz, ilk etiket ile ilk metin kutusunu yan yana, sonraki ikilileri de yine yan yana istiyoruz. O
halde, ana düzeni oluşturan kutu pencere düzeninin ilk satırına bir başka kutu pencere düzeni yerleştirmeliyiz. İkinci
kutu pencere düzeninine eklediğimiz parçacıklar zaten yan yana görünecektir. Anlatmak istediğimi aşağıdaki şekilde
çizdim:
Yukarıdaki çizimde gördüğünüz pencere düzenini oluşturacak program Liste 3.4‘dadır.
3.2. Pencere Düzenleri
11
Kivy Mobil Programlama, Sürüm 0.1
Liste 3.4: girisFormu.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{n+nn}{kivy.uix.widget} \PYG{k+kn}{import} \PYG{n}{Widget}
\PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{n+nn}{kivy.uix.textinput} \PYG{k+kn}{import} \PYG{n}{TextInput}
\PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k}{class} \PYG{n+nc}{girisFormu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{duzen} \PYG{o}{=} \PYG{n}{BoxLayout}\PYG{p}{(}\PYG{n}{orientation}\PYG{o}{=}\PYG{l+s+
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}1} \PYG{o}{=} \PYG{n}{BoxLayout}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}1}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{
\PYG{n}{kullanici\PYGZus{}adi} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}1}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{duzen\PYGZus{}satir\PYGZ
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}2} \PYG{o}{=} \PYG{n}{BoxLayout}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}2}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{
\PYG{n}{parola} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}2}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{duzen\PYGZus{}satir\PYGZ
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}3} \PYG{o}{=} \PYG{n}{BoxLayout}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}3}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{
\PYG{n}{gir\PYGZus{}dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+
12
Bölüm 3. Temel Bilgiler
Kivy Mobil Programlama, Sürüm 0.1
\PYG{n}{duzen\PYGZus{}satir\PYGZus{}3}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{duzen\PYGZus{}satir\PYGZ
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{title} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Gi
\PYG{k}{return} \PYG{n}{duzen}
\PYG{n}{girisFormu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Liste 3.4‘deki programı çalıştırdığımızda bize Şekil 3.2 ‘deki pencerenin aynısını verecektir.
3.2.3 Diğer Pencere Düzenleri
Kivy yukarıda anlattığımız, pencere düzenlerinden daha fazlasını sunar. Tüm pencere düzenlerini şöyle özatleyebiliriz.
AnchorLayout: Grafik parçacıkları ‘top’ (üst), ‘bottom’ (alt), ‘left’ (sol), ‘right’ (sağ) veya ‘center’ (orta) konuma
yerleştirielbilirler.
BoxLayout: Grafik parçacıkları ‘vertical’ (dikey) veya ‘horizontal’ (yatay) yönelimli olarak yerleştirilebilirler.
FloatLayout: Grafik parçacıkları istenilen herhangi bir konuma yerleştirilebilirler.
RelativeLayout: Çocuk grafik parçacıkları düzene göreceli olarak yerleştirilebilirler.
GridLayout: Grafik parçacıkları ızgara şeklinde yerleştirilebilirler.
PageLayout: Çoklu sayfa düzeni oluşturmak için kullanılabilir.
ScatterLayout: Grafik parçacıkları RelativeLayout’da olduğu gibi yerleştirilebilir ancak bunlar dönrürülebilir ve ölçeklenebilir.
StackLayout: Grafik parçacıkları üst-alt ve sağ-sol’a kaydırılacak şekilde yerleştirilebilir.
İhtiyaç oldukça bu pencere düzenlerini kullanacağız ve oralarda daha ayrıntılı açıklayacağız.
Pencere düzenlerinin kod yazarak oluşturulması, mekanik bir işlemi tekrarlamaktır. Kivy’de bizi bu dertten kurtarack
bir diğer yöntem vardır: kv lang (veya kv dili). Bunu Kivy Dili: kv (kv lang) bölümünde anlatacağız.
3.2. Pencere Düzenleri
13
Kivy Mobil Programlama, Sürüm 0.1
14
Bölüm 3. Temel Bilgiler
BÖLÜM 4
Kivy Dili: kv (kv lang)
Kivy pencere düzenlerini oluşturmak için muhteşem bir dil sunmaktadır: kv Dili. Bu dili biraz HTML’ye biraz da
css’ye benzetebilirsiniz. Bu bölümde kv dilini anlatmaya çalışacağız.
4.1 “Merhaba Dünya” yeniden
merhabaDunya.py programında ekrandaki “Merhaba Dünya” yazısını program kodu içerisinde bir etiket oluşturup, bu
etiketin metinini değiştirerek yapmıştık. Bu etiketi daha sonra düzen olarak geri döndürmüştük (return Label()).
Şimdi aynı pencereyi kv dilini kullanrak yapacağız. Önce program kodumuzu main.py‘deki gibi yazalım. Bu kodda
hiçbir değişiklik yapmadan birçok pencere oluşturacağız.
Liste 4.1: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k}{class} \PYG{n+nc}{girisFormu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
\PYG{n}{girisFormu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Gördüğünüz gibi bu program hiçbirşey döndürmüyor. Sadece basit bir pencere oluşturuyor. Pencere içeriğini kv dili
oluşturacağız. Şimdi dosyasını girisformu.kv programını kaydettiğiniz aynı dizinine (klasöre) kaydedin.
Liste 4.2: girisformu.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 Label:
text: \PYGZdq{}Merhaba Dünya\PYGZdq{}
Bu dosyanın adı, python programının dosya adı değil, uygulamanın adı ile aynı olacaktır. Eğer uygulamanızın adı
kullaniciGirisFormu() ise kv dosyasının adı kullanicigirisformu.kv olacaktır. Dosya adında küçük
harfleri kullanmanızı yeğlerim. Buradaki girisformu.kv oldukça basit bir yapıya sahip.Sadece iki satırdan ibaret ilk
satır pencerede bir etiketin olacağı (Label), ikinci satırda ise bu etiketin üzerinde yazacak metni (text) belirtmektedir.
Tıpkı Python’da olduğu gibi kv dilinde de girintiler (indendation) önemlidir. Birinci satır penceredeki grafik parçacığının ismini belirtmektedir. Grafik parçacığının isminden sonra iki nokta üst üste konulup sonraki satırda (sanki işlev
tanımlar gibi), bu grafik parçacığının özelliklerine ait yapılanmayı biraz içerde başlatıyoruz.
15
Kivy Mobil Programlama, Sürüm 0.1
main.py programını çalıştırdığınızda yine Şekil 3.1‘deki gibi bir pencere açılacaktır.
4.2 Kutu Pencere Düzeni (Box Layout)
Temel Bilgiler bölümündeki Pencere Düzenleri‘ni hatırlayın. Orada ızgara pencere düzenini oluşturmak için
GridLayout() sınıfını kullanmıştık. kv dilinde de yine grafik parcacıklarının ismini kullanacağız. Kutu pencere
düzeni BoxGridLayout() sınıfı ile oluşturulur. O halde kv dilinde BoxLayout ile kutu pencere düzenini oluşturabiliriz. Liste 4.3‘deki gibi değiştirin.
Liste 4.3: girisformu.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 BoxLayout:
Label:
text: \PYGZdq{}Merhaba Dünya\PYGZdq{}
Label:
text: \PYGZdq{}Merhaba Kivy\PYGZdq{}
main.py programını tekrar çalıştırdığımızda Şekil 4.1‘deki gibi bir pencere açılacaktır.
Şekil 4.1: Kutu Pencere Düzeni
Bu pencerede yan yana iki tane etiketin oluştuğunu görüyorsunuz. Kutu pencere düzeninin ön tanımlı yönelimi “yatay”dır (vertical). Eğer dikey olarak yönelndirmek istiyorsanız, pencere düzeninine orientation: ‘vertical’ satırını Liste
4.4‘deki gibi eklemelisiniz.
Liste 4.4: girisformu.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
text: \PYGZdq{}Merhaba Dünya\PYGZdq{}
Label:
text: \PYGZdq{}Merhaba Kivy\PYGZdq{}
Şimdi Şekil 4.2‘deki gibi etiketlerimiz dikey olarak yerleşecektir.
16
Bölüm 4. Kivy Dili: kv (kv lang)
Kivy Mobil Programlama, Sürüm 0.1
Şekil 4.2: Kutu Pencere Düzeni: Dikey Yönelimli
4.3 Izgara Pencere Düzeni (Grid Layout)
Izgara pencere düzenini dah önce görmüştük. Sütun ve satırlardan oluşuyordu. Şimdi Izgara Pencere düzenini kv dili
oluşturacağız. girisformu.kv programını Liste 4.5‘deki gibi yazın. Metin kutularının TerxtInput ile oluşturulduğuna dikkat etmelisiniz.
Liste 4.5: girisformu.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 GridLayout:
Label:
text: \PYGZdq{}Kullanıcı Adı:\PYGZdq{}
TextInput:
Label:
text: \PYGZdq{}Parola:\PYGZdq{}
TextInput:
Widget:
Button:
text: \PYGZdq{}Gir\PYGZdq{}
Burada iki sütunlu olması için cols: 2 satırını eklediğimize dikkat etmelisiniz. Yine aynı soruyu sormak istiyorum, 9.
satırdaki Widget garfik parçacığını niçin koymuş olabiliriz? main.py programını çalıştırdığınızda Şekil 4.3‘deki gibi
görünecektir.
Şekil 4.3: Izgara Düzeni: Kullanıcı Giriş Formu
Aslında ızgara düzenini, kutu düzenlerini iç içe yazarakda yapabiliriz. Nihayetinde, ızgara düzeni dediğimiz, alt alta
4.3. Izgara Pencere Düzeni (Grid Layout)
17
Kivy Mobil Programlama, Sürüm 0.1
yerleştirilmiş (dikey yönelimli), yatay yönelimli kutulardan oluşmaktadır. Liste 4.6‘yi inceleyin.
Liste 4.6: girisformu.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 BoxLayout:
orientation: \PYGZdq{}vertical\PYGZdq{}
BoxLayout:
Label:
text: \PYGZdq{}Kullanıcı Adı:\PYGZdq{}
TextInput:
BoxLayout:
Label:
text: \PYGZdq{}Parola:\PYGZdq{}
TextInput:
BoxLayout:
Widget:
Button:
text: \PYGZdq{}Gir\PYGZdq{}
Burada gördüğünüz gibi, en üstte bir tane dikey yönelimli kutu pencere düzeni ve bunun altında üç tane yatay yönelimli
kutu pencere düzeni yerleştirmiş olduk. İşimizi biraz uzattık, ancak konuyu anlamanız açısından bu örneği verdik.
Liste 4.6 ve Liste 4.5 aynı görünütüyü oluşturur. Python programını (burada main.py) hiç değiştirmeden birçok kv
dosyası ile kullandık ve serferinde farklı pencereler elde ettik. Liste 4.6‘deki 12. satırı (Widget: yazan satır) silersek,
nasıl bir değişiklik oluşur? Bunu denemelisiniz.
4.4 Parçacık Boyutları (size_hint)
Grafik parçacıklarının görünür boyutlarını size_hint_x ve size_hint_y ayarlayabilirsiniz. Anlayacağınız
üzere, size_hint_x yatay boyutun, size_hint_y ise dikey boyutun büyüklüğünü ayarlar. Ayarlamalar oran
olarak yapılır. Örneğin yatay olarak yerleştirilmiş iki parcacıktan birisinin boyutu 1, diğerinin 4 ise, toplamı 5 yapacağından, ilk parcacık yatayın %20 sini, diğeri %80’nin kaplayacaktır. 3:2 olduğunda ne olabilir? İster yatay, ister dikey
olsun birisine boyut bildirdiğinizde, diğerlerinede bildirmek durumundasınız. Aksi halde anlamsız olacaktır.
girisformu.kv dosyasını Liste 4.5‘deki gibi düzenleyelim.
Liste 4.7: girisformu.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 BoxLayout:
orientation: \PYGZdq{}vertical\PYGZdq{}
BoxLayout:
\PYGZsh{} 1. satırı oluşturan yatay kutu
size\PYGZus{}hint\PYGZus{}y: 3
Label:
text: \PYGZdq{}Kullanıcı Adı:\PYGZdq{}
size\PYGZus{}hint\PYGZus{}x: 1
TextInput:
size\PYGZus{}hint\PYGZus{}x: 3
BoxLayout:
18
Bölüm 4. Kivy Dili: kv (kv lang)
Kivy Mobil Programlama, Sürüm 0.1
\PYGZsh{} 2. satırı oluşturan yatay kutu
size\PYGZus{}hint\PYGZus{}y: 2
Label:
text: \PYGZdq{}Parola:\PYGZdq{}
TextInput:
BoxLayout:
\PYGZsh{} 3. satırı oluşturan yatay kutu
size\PYGZus{}hint\PYGZus{}y: 1
Button:
text: \PYGZdq{}Gir\PYGZdq{}
Bunun üzerinde biraz konuşalım. Gördüğünüz gibi üç satır var. Her bir satır bir yatay kutu pencere düzeni tarafından
oluşturulmakta, satırlar ise en üstteki dikey pencere kutusu ile alt alta getiriliyor. Üç adet satırın yükseklikleri sırası
ile size_hint_y: 3, size_hint_y: 2 ve size_hint_y: 1 ile ayarlanmıştır (1., 2. ve 3. satırları oluşturan
yatay kutular). Bunun anlamı dikey boyutun yarısı 1. yatay kutu tarafından kaplanacaktır. Geri kalan yarısının %66.6’sı
2. yatay kutu ve %33.3’ü ise 3. yatay kutu tarafından kaplanacaktır. Yatay büyüklük ise sadece 1. yatay kutu için
ayarlanmıştır. %25’i etiket tarafından (Kullanıcı Adı etiketi), %75’i ise metin kutusu tarafından kullanılacaktır.
Programımızı çalıştırdığımızda Şekil 4.3‘deki gibi görünecektir.
Şekil 4.4: Boyutlandırılmış Giriş Formu
4.5 İkisi Bir Arada
Aslında bu kadar küçük programlar için kv içeriğini farklı bir dosyaya yazmaya gerek yok. Bunun yerine Python
programı içerisine kv içeriğini de yazabiliriz. Liste 4.8‘de bunu görüyorsunuz.
Liste 4.8: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
4.5. İkisi Bir Arada
19
Kivy Mobil Programlama, Sürüm 0.1
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.lang} \PYG{k+kn}{import} \PYG{n}{Builder}
\PYG{n}{kv}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}\PYGZsq{}\PYGZsq{}}
\PYG{l+s+s1}{BoxLayout:}
\PYG{l+s+s1}{
orientation: }\PYG{l+s+s1}{\PYGZdq{}}\PYG{l+s+s1}{vertical}\PYG{l+s+s1}{\PYGZdq{}}
\PYG{l+s+s1}{
BoxLayout:}
\PYG{l+s+s1}{
Label:}
\PYG{l+s+s1}{
text: }\PYG{l+s+s1}{\PYGZdq{}}\PYG{l+s+s1}{Kullanıcı Adı:}\PYG{l+s+s1}{\PYGZ
\PYG{l+s+s1}{
TextInput:}
\PYG{l+s+s1}{
BoxLayout:}
\PYG{l+s+s1}{
Label:}
\PYG{l+s+s1}{
text: }\PYG{l+s+s1}{\PYGZdq{}}\PYG{l+s+s1}{Parola:}\PYG{l+s+s1}{\PYGZdq{}}
\PYG{l+s+s1}{
TextInput:}
\PYG{l+s+s1}{
password: True}
\PYG{l+s+s1}{
BoxLayout:}
\PYG{l+s+s1}{
Widget:}
\PYG{l+s+s1}{
Button:}
\PYG{l+s+s1}{
text: }\PYG{l+s+s1}{\PYGZdq{}}\PYG{l+s+s1}{Gir}\PYG{l+s+s1}{\PYGZdq{}}
\PYG{l+s+s1}{\PYGZsq{}\PYGZsq{}\PYGZsq{}}
\PYG{k}{class} \PYG{n+nc}{girisFormu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{=}\PYG{n}{Builder}\PYG{o}{.}\PYG{n}{load\PY
\PYG{k}{return} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}
\PYG{n}{girisFormu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Gördüğünüz gibi, kv içeriği bir Python programı içerisindeki bir cümleden alınıyor ve Builder nesnesinin
load_string() özelliği ile yükleniyor. Şimdilik neden ana pencerenin self.root değişkenine aktarılıp
build() tarafından döndürüldüğünden bahsetmeyeceğiz. Çeşitli pencere düzenleri, ve grafik parçacığı büyüklükleri
ile deneyiniz. Buradaki bir diğer değişiklik, parolanın yazılacağı metin kutusunun gerçek bir parola alanı olduğudur.
Bunu password: True özelliği ile yaptık. Artık bu alana yazılırken, yazılan karakterler görüntülenmez yerine
yıldız (*) görüntülenir.
Bir metin kutusuna (TextInput), parola alanı yapacaksak, password özelliğinin değerini True yapmalısınız. Bunu kod
ile yapmak istiyorsanız
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{parola} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{n}{password}\PYG{o}{=}\PYG{n+n
ya da, daha sonra yapmak için:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{parola} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{parola}\PYG{o}{.}\PYG{n}{password}\PYG{o}{=}\PYG{n+nb+bp}{True}
kv dili ile pencereleri oluşturmayı öğrendiğimize göre, şimdi biraz bu pencereleri işler hale getirmeye geldi. Sonraki
bölümde garfik parçacıkları ile kullanıcı etkileşmesinin nasıl gerçekleştiğini göreceğiz.
20
Bölüm 4. Kivy Dili: kv (kv lang)
BÖLÜM 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.
Liste 5.1: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k}{class} \PYG{n+nc}{olayUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{metni\PYGZus{}degistir}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{ne
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s1}{\PYG
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{duzen}\PYG{o}{=}\PYG{n}{BoxLayout}\PYG{p}{(}\PYG{p}{)}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\P
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o}{.}\PY
\PYG{k}{return} \PYG{n}{duzen}
\PYG{n}{olayUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
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)
21
Kivy Mobil Programlama, Sürüm 0.1
argüman olarak gönderilir. Aslında dugme‘yi self‘in özelliği yapmadan, gelen nesne üzerinden de metni değiştirebilirdik:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{Tıkladı
aynı görevi görürdü. Şimdi aynı programı kv lang ile yazalım. Programımızı Liste 5.2‘da görüyorsunuz.
Liste 5.2: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k}{class} \PYG{n+nc}{olayUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{metni\PYGZus{}degistir}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{dugme}\PYG{
\PYG{n}{olayUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
İlgili kv dosyasını Liste 5.3‘da görüyorsunuz.
Liste 5.3: olayuyg.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 BoxLayout:
Button:
id: dugme
text: \PYGZsq{}Değiştir\PYGZsq{}
on\PYGZus{}press: app.metni\PYGZus{}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.
Liste 5.4: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
22
Bölüm 5. Olaylar ve Popup
Kivy Mobil Programlama, Sürüm 0.1
\PYG{k}{class} \PYG{n+nc}{olayUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{metni\PYGZus{}degistir}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{girilen\PYGZus{}metin} \PYG{o}{=} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{etiket}\PYG
\PYG{n}{olayUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Bu programla kullanacağımız kv dosyasını da Liste 5.5‘da görüyorsunuz.
Liste 5.5: olayuyg.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
TextInput:
id: metin\PYGZus{}girdisi
Label:
text: \PYGZsq{}Adınızı yukarıya yazın...\PYGZsq{}
id: etiket
markup: True
Button:
id: dugme
text: \PYGZsq{}Değiştir\PYGZsq{}
on\PYGZus{}press: app.metni\PYGZus{}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.
Şekil 5.1: Girilen metnin etikete yazılması
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
5.1. İşaret Dili (markup)
23
Kivy Mobil Programlama, Sürüm 0.1
etiket tanımlamış olsaydık, işaret dilini etkinleştirmek için
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{etiket} \PYG{o}{=} \PYG{n}{Label}\PYG{p}{(}\PYG{n}{markup}\PYG{o}{=}\PYG{n+nb+bp}{
diyebilirdik. Ya da daha önceden tanımlanmış bir etiket nesnesi için:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{etiket}\PYG{o}{.}\PYG{n}{markup}\PYG{o}{=}\PYG{n+nb+bp}{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:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{etiket}\
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.
Şekil 5.2: Etiketlerde renk kullanımı
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.
24
Bölüm 5. Olaylar ve Popup
Kivy Mobil Programlama, Sürüm 0.1
[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.
Liste 5.6: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k}{class} \PYG{n+nc}{olayUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{yazdir}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{,} \
\PYG{k}{print} \PYG{n}{deger}
\PYG{c+c1}{\PYGZsh{}nesne.text = deger}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{etiket} \PYG{o}{=} \PYG{n}{Label}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s1}{\PYGZs
\PYG{n}{etiket}\PYG{o}{.}\PYG{n}{markup}\PYG{o}{=}\PYG{n+nb+bp}{True}
\PYG{n}{etiket}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}ref\PYGZus{}press}\PYG{o}{
\PYG{k}{return} \PYG{n}{etiket}
\PYG{n}{olayUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Eğer yazdir() işlevini şu şekilde değiştirecek olursanız:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{text} \PYG{o}{=} \PYG{n}{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.
Liste 5.7: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.popup} \PYG{k+kn}{import} \PYG{n}{Popup}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k}{class} \PYG{n+nc}{olayUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
5.2. Popup Pencere: (popup)
25
Kivy Mobil Programlama, Sürüm 0.1
\PYG{k}{def} \PYG{n+nf}{popAc}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)}\PY
\PYG{n}{icerik}\PYG{o}{=}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{
\PYG{n}{popup} \PYG{o}{=} \PYG{n}{Popup}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PYG{l+s+s1}{\PYGZs
\PYG{n}{content}\PYG{o}{=}\PYG{n}{icerik}\PYG{p}{,}
\PYG{n}{size\PYGZus{}hint}\PYG{o}{=}\PYG{p}{(}\PYG{n+nb+bp}{None}\PYG{p}{,} \PY
\PYG{n}{icerik}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}touch\PYGZus{}down}\PYG{o}
\PYG{n}{popup}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{return} \PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l
\PYG{n}{olayUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
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.
Liste 5.8: olayuyg.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}olayUyg\PYGZgt{}:
BoxLayout:
orientation: \PYGZdq{}vertical\PYGZdq{}
Label:
id: ana\PYGZus{}pencere\PYGZus{}etiket
markup: True
text: \PYGZdq{}Aşağıdaki düğmeye tıklarsan [b][i]Popup[/i][/b] pencere açılır.\PYGZdq{}
size\PYGZus{}hint\PYGZus{}y: 3
Button:
text: \PYGZdq{}Popup Açma Düğmesi\PYGZdq{}
on\PYGZus{}press: app.popAc()
size\PYGZus{}hint\PYGZus{}y: 1
\PYGZlt{}PopUpPencere\PYGZgt{}:
size\PYGZus{}hint: (None, None)
size: (3, 1)
auto\PYGZus{}dismiss: False
26
Bölüm 5. Olaylar ve Popup
Kivy Mobil Programlama, Sürüm 0.1
title: \PYGZdq{}Adınız:\PYGZdq{}
\PYGZsh{}on\PYGZus{}touch\PYGZus{}down: self.dismiss()
BoxLayout:
TextInput:
id: girilen\PYGZus{}ad
size\PYGZus{}hint\PYGZus{}x: 3
Button:
text: \PYGZdq{}Tamam\PYGZdq{}
size\PYGZus{}hint\PYGZus{}x: 1
on\PYGZus{}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:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{popup}\PYG{o}{=}\PYG{n}{PopUpPencere}\PYG{p}{(}\PYG{p
ş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.
5.2. Popup Pencere: (popup)
27
Kivy Mobil Programlama, Sürüm 0.1
Liste 5.9: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.popup} \PYG{k+kn}{import} \PYG{n}{Popup}
\PYG{k}{class} \PYG{n+nc}{PopUpPencere}\PYG{p}{(}\PYG{n}{Popup}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{olayDugme}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{uyg}\PYG{p}{)}\
\PYG{n}{ad}\PYG{o}{=}\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{girilen\PYGZu
\PYG{n}{uyg}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{ana\PYGZus{}pencer
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dismiss}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{class} \PYG{n+nc}{olayUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{popAc}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{popup}\PYG{o}{=}\PYG{n}{PopUpPencere}\PYG{p}{(}\PYG{p}{)
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{popup}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{olayUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
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.
Şekil 5.3: Popup’ın açılması
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
28
Bölüm 5. Olaylar ve Popup
Kivy Mobil Programlama, Sürüm 0.1
Şekil 5.4: Popup işevinden Ana Penceredeki metnin değiştirilmesi.
sahibi olduk.
5.2. Popup Pencere: (popup)
29
Kivy Mobil Programlama, Sürüm 0.1
30
Bölüm 5. Olaylar ve Popup
BÖLÜM 6
Metin Düzenleyici
Birçok yeni programcı, programların çok basit şekilde hazırlanabileceğini düşünür. Oysa ki en küçük programda bile
çok fazla düşlünülecek ve yapılacak iş vardır. Bu bölümde basit bir metin düzenleyici yapacağız. Elbette yapacağımız
metin düzenleyici üretim açamlı olmayacaktır. Sadece bir program yazılırken, programcıların nelere dikkat etmeleri
gerektiği, nereleri düşünmeleri gerektiğine bir ışık tutacağız. Basit bir metin düzenleyici yazmak için ne kadar çok
yapılacak iş olduğunu göreceksiniz. Bir programı yazmaya başlayınca, düşünmenin sınırı ve yapılacakların sonu olmadığını göreceksiniz. Biz burada bir yol açalım, gerisini size bırakacağız.
6.1 Ana Pencere
Buradaki metin düzenleyici basitçe bir metin alanı ve kullanıcıya dosyasını açıp kaydedebileceği birkaç seçenek sunmaktan ibaret (tamamı bu değildir elbette) olacak. O halde öncelikle ana penceremizi hazırlayalım, bunun için şimdilik
metin alanımızı ve altına işlem yapmayan birkaç düğme koyalım. Daha sonra bu düğmelere işlerlik kazandıracağız.
main.py dosyasını Liste 6.1‘deki gibi yazalım.
Liste 6.1: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{import} \PYG{n+nn}{os}\PYG{o}{,} \PYG{n+nn}{sys}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.popup} \PYG{k+kn}{import} \PYG{n}{Popup}
\PYG{k}{class} \PYG{n+nc}{metinDuzenleyici}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
\PYG{n}{metinDuzenleyici}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Bu programda bilmediğimiz hiçbirşey yok. os ve sys modüllerini neden içerdiğimizi ileride göreceksiniz. Şimdi de,
bu program tarafından kullanılacak kv dosyasını Liste 6.2‘deki gibi yazalım:
31
Kivy Mobil Programlama, Sürüm 0.1
Liste 6.2: metinduzenleyici.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}metinDuzenleyici\PYGZgt{}:
BoxLayout:
orientation: \PYGZdq{}vertical\PYGZdq{}
exit\PYGZus{}on\PYGZus{}escape: False
TextInput:
size\PYGZus{}hint\PYGZus{}y: 9
id: metin
multiline: True
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
Button:
text: \PYGZdq{}Aç\PYGZdq{}
on\PYGZus{}press: pass
Button:
text: \PYGZdq{}Kaydet\PYGZdq{}
on\PYGZus{}press: pass
Button:
text: \PYGZdq{}Farklı Kaydet\PYGZdq{}
on\PYGZus{}press: pass
Button:
text: \PYGZdq{}Yeni\PYGZdq{}
on\PYGZus{}press: pass
Bu dosyada bilmediğimiz sadece TextInput parçacığının multiline özelliğine True değerinin atanmış olmasıdır.
TextInput parçacığını
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{metin} \PYG{o}{=} \PYG{n}{TextInput}\PYG{p}{(}\PYG{n}{multiline}\PYG{o}{=}\PYG{n+n
şeklinde tanımlayacak olursak, çok satırlı bir metin girdi alanı elde etmiş oluruz. TextInput parçacığı ön tanımlı
olarak tek satırdan oluşur, multiline özelliğine True değeri atamkla çok satırlı bir metin giriş alanı elde etmiş
oluruz ki, bir metin düzenleyicinin metin yazılacak alanı tam da bu yaptığımız gibidir.
main.py programı çalıştırdığımızda metin düzenleyicimizin penceresi Sonucu Şekil 6.1 ‘deki gibi açılacaktır.
Şimdi yukarıdaki düğmelere tıklayın bakalım dosya açacak mı, dosyanızı kaydedecek mi? Sizce olur mu? Neden olmasın ki? Ben düğmeyi koydum, program da gitsin dosyamı kaydedeceğini anlasın ve kaydetsin. Benzer cümleleri
her sınıfımda kullanırım. Ancak ne yazıkki bu programları yazanlar, bizim koyduğumuz düğmelerin (ya da menülerin)
üzerindeki metinlere bakarak, ne iş yapmak istediğimizi anlamayacak kadar becereksizler. Öyle mi? Elbette değil. Bir
düğme koyduysanız, ona tıklandığında ne yapılması gerektiğini siz yazacaksınız, bir başkası değil. Bu kadar söylendikten sonra gelin, bu düğmelere işlerlik kazandıralım. Öncelikle “Farklı Kaydet” düğmesinden başlayalım. Neden
mi? Çünkü “Kaydet” dedğimizde, daha önceden bir dosya adı verilmemişse “Farklı Kaydet” çağrılacaktır.
6.2 Farklı Kaydet
Bir dosyayı kaydetmek için, öncelikle kaydedilecek klasörün belirtilmesi ve daha sonra da dosya adının girilmesi
gerekir. Eğer kullanıcıya basitçe bir metin kurtusu sağlayıp buraya dosyanın tam patikasını yazmasını isterseniz (örneğin C:\dosyalarım\odevlerim\fizik\newton.txt şeklinde), kusura bakmayın ama programınızı kimse
kullanmaz. 1990’lı yıllarda olsaydınız buna kimse itirtaz etmezdi ancak şimdi GUI (Grafik Kullanıcı Arayüzü) icat
edildi. O halde klasörler arasında gezinti yapabilecek bir arayüze ihtiyacımız var. Bun kendiniz yapabilirsiniz. Nasıl
32
Bölüm 6. Metin Düzenleyici
Kivy Mobil Programlama, Sürüm 0.1
Şekil 6.1: Metin Düzenleyicimiz Kullanıma Hazır :-)
6.2. Farklı Kaydet
33
Kivy Mobil Programlama, Sürüm 0.1
mı? os.listdir()‘i biliyorsunuz. Her bir elemanı ızgara düzenine bir düğme olarak yerleştirip gezinti sağlayabilirsiniz. Ama bunu yapmayın. Çünkü Kivy geliştiricileri bizim için daha iyisini yapmış: FileChooserListView. Bu
grafik parçacığı bize dizinler arası gezinti yapmamızı sağlayacak bir araç sunmaktadır. Bu parçacığın filters özelliği sayesinde, hangi dosyaları liseteleyeciğimizi de belirtebiliyoruz (aşağıda [’*.*’] kodu tüm dosyaların listeleneceğini göstermektedir. Üstelik bir seçim yaptığımızda on_selection olayı sayesinde, seçim ile ilgili işlemlerimizi yapabiliyoruz. O halde bu parçacığı en üste koyalım, altına bir adet dosya adının yazılabileceği metin kutusu,
onun altına da iki adet düğme: “Kaydet”, “Vazgeç”. O halde metin düzenleyicimizin pencerelerinin oluşturulduğu
metinduzenleyici.kv dosyasına aşağıdaki gibi yeni bir form ekleyelim:
Liste 6.3: FakrliKaydetForm
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}farkliKaydetForm\PYGZgt{}:
size\PYGZus{}hint: (.9, .9)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
FileChooserListView:
size\PYGZus{}hint\PYGZus{}y: 8
filters: [\PYGZsq{}*.*\PYGZsq{}]
path: app.son\PYGZus{}patika
on\PYGZus{}selection: pass
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
text: \PYGZdq{}Dosya Adı:\PYGZdq{}
size\PYGZus{}hint\PYGZus{}x: 2
id: dosya\PYGZus{}adi
size\PYGZus{}hint\PYGZus{}x: 8
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
text: \PYGZdq{}Kaydet\PYGZdq{}
on\PYGZus{}press: pass
Button:
text: \PYGZdq{}Vazgeç\PYGZdq{}
on\PYGZus{}press: root.dismiss()
id: dosya\PYGZus{}secim
Label:
TextInput:
Button:
Bu formu kullanacak bir sınıf tanımlamak gerekiyor. Bunu class metinDuzenleyici(App) satırından önce
aşağıdaki kodları ekleyerek yapabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{class} \PYG{n+nc}{farkliKaydetForm}\PYG{p}{(}\PYG{n}{Popup}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
Dosya ismini ve kaydedildiği patikayı takip etmemiz gerekmektedir. Nedenini şöyle açıklayabiliriz, eğer bir dosya
açılmış (ya da bir isimle kaydedilmiş) ise, dosya ismi var olacağından tekrar kaydedilmesi sırasında bı dosya ismini
kullanmamız gerekmektedir. Dosya ismi gerekli ise, kaydedildiği klasör de gereklidir. O halde tüm programımız içerisinde dosya ismi ve patikayı kullanabileceğimizden, build() işlevine aşağıdaki satırları eklememiz gerekecek.
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{o}{=} \PYG{n}{os}\PYG{o}{.}\P
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}dosya}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{
34
Bölüm 6. Metin Düzenleyici
Kivy Mobil Programlama, Sürüm 0.1
Bu satırları ekledikten sonra build() işlevindeki pass ifadesine gerek kalmayacak.
Sanırım main.py programının başında os modülünü çağırma nedenimizi anladınız. Burada son patika ön tanımlı
olarak programın çalıştığı patikayı göstermektedir, son dosya ise boş bir cümledir, yani dosya adı yoktur.
Ana pencerede “Farklı Kaydet” düğmesine tıklandığında farkliKaydetForm‘nun açılabilmesi için, üzerinde
“Farklı Kaydet” yazan düğmeye tıklandığında bir işlevin çağrılması ve bu işlev altından da bu formu gösterebilmemiz gerekiyor. O halde bu düğmenin on_press özelliğini farkliKaydetDialog() işlevini çağıracak şekilde
aşağıdaki gibi değiştirelim (Liste 6.2‘deki 18, 19 ve 20. satırlar):
=
{}=
{}@default
=0=1=2=0=1=2Button:
text: \PYGZdq{}Farklı Kaydet\PYGZdq{}
on\PYGZus{}press: app.farkliKaydetDialog()
İşimiz henüz bitmedi, çünükü düğmeye tıklandığında çağrılacak olan işlevi yazmadık, bunun için build() işlevinden
hemen önce aşağıdaki işlevi tanımlayalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{farkliKaydetDialog}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{
\PYG{n}{form} \PYG{o}{=} \PYG{n}{farkliKaydetForm}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{form}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
Artık “Farklı Kaydet” düğmesine tıkladığımzda yeni bir pencere açılmaktadır. Açılacak olan pencereyi Şekil 6.2 ‘de
görüyorsunuz:
Peki bu pencere şu anda ne iş yapar? Sadece dosya ve klasörleri listeler (bunuda biz yapmadık FakrliKaydetForm‘de
7. satırda tanımladığımız FileChooserListView parçacığı yapıyor). Haa birde çok büyük bir iş olan “Vazgeç”
düğmesine tıklandığında pencere kapanıyor. Sanırım bunu bizden başka başarabilecek kimse de yok :-). Peki bu nasıl
gerçekleşiyor? Pencerenin kapanmasını bizim yazdığımız kod sağlamkta, şaka yapmıyorum :-) Peki nersi? Yanılmıyorsam (yanılıyorsam lütfen beni uyarın!), FakrliKaydetForm‘deki 30. satır bu işi yapıyor olmalı.
Az zamanda çok işler başardığımızı söylemek isterdim, ancak gerçek bu değil. Daha henüz işe yarar birşey yapmadık. Öncelikle FileChooserListView parçacığının gösterdiği dosya isimleri üzerine tıklandığında (diğer
bir deyişle var olan dosya ismini seçip bu dosya üzerine kaydetmek isteyebilir, aman dikkat !! çok tehlikeli,
kaydetmeden önce onay almalısınız, bunu size bırakıyoruz) bu dosya isminin dosya adı yazılacak olan (id‘si
dosya_adi olan TextInput parçacığı) metin kutusunda belirmelidir. Bunu nasıl yapacağız? Daha önce demiştik ya
on_selection özelliği ile. Bu özelliği dosya seçimi işleminden sonra çağrılacak olan işleve bağlayabiliriz. Bunun
için FileChooserListView parçacığının on_selection özelliğini aşağıdaki gibi değiştirin (FakrliKaydetForm‘de 12. satırı aşağıdaki gibi değiştirin):
=
{}=
{}@default
=0=1=2=0=1=2on\PYGZus{}selection: app.farkliKaydetSecim(root)
Burada ne yapılıyor? Her sonunun cevabını verdik te bunun cevabını mı esirgeyelim? Burada yapılan iş, formun kendisini uygulamanın farkliKaydetSecim() işlevine argüman olarak göndermek. Gerisini bu işlev halletmektedir.
O zaman bu işelvi yazmalıyız. build()‘den hemen önce aşağıdaki işlevi tanımlayalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{farkliKaydetSecim}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{
\PYG{n}{secilen\PYGZus{}dosya}\PYG{o}{=}\PYG{n}{form}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{dosy
\PYG{k}{if} \PYG{n}{secilen\PYGZus{}dosya}\PYG{p}{:}
6.2. Farklı Kaydet
35
Kivy Mobil Programlama, Sürüm 0.1
Şekil 6.2: Farklı Kaydet Penceresi
36
Bölüm 6. Metin Düzenleyici
Kivy Mobil Programlama, Sürüm 0.1
\PYG{k}{if} \PYG{n+nb}{len}\PYG{p}{(}\PYG{n}{secilen\PYGZus{}dosya}\PYG{p}{)}\PYG{o}{\PYGZgt{
\PYG{n}{dosyaAdi}\PYG{o}{=}\PYG{n}{os}\PYG{o}{.}\PYG{n}{path}\PYG{o}{.}\PYG{n}{split}\PYG
\PYG{n}{form}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{dosya\PYGZus{}adi}\PYG{o}{.}\PYG{n}{
Bu işleve farkliKaydetForm‘nun kendisi argüman olarak geliyordu, bunu form değişkenine aktardık.
FileChooserListView nesneninden seçilen dosyayı selection özelliği ile alabaliriz. Bu bize seçilen tüm
dosyaları (çoklu seçim yapılabilir, multiselect özelliğinin değeri True yapılarak). Ön tanımlı olarark sadece bir dosya
seçilebildiğinden, ilk dosyayı patika ve dosya adı olarak ayırdıktan sonra yaptığımız iş dosya adını formumuzda ids’si
dosya_adi olan metin kutusunda göstermektir.
Şimdi gelelim “Kaydet” düğmesine tıklandığında yapılacak olan işe: formadki metin kutusundan dosya adını alacak ve
diske yazma işlemi gerçekleştirilecek. Diske yazma işlemini farklı bir işlevde yapacağız, çünkü ana pencerede “Kaydet” düğmesine tıklandığında da bu işlevi çağıracağız. Önce “Kaydet” düğmesine tıklandığında çağrılacak olan işlevi
belirtmeliyiz, ardındanda bu pencereyi kapatmalıyız. O halde FakrliKaydetForm deki 27. satırı şu şekilde değiştirelim:
=
{}=
{}@default
=0=1=2=0=1=2on\PYGZus{}press: app.farkiKaydetIslevi(root); root.dismiss()
Gelelim farkiKaydetIslevi() işlevine: bu işlevi build() den hemen önce şu şekilde tanımlayabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{farkiKaydetIslevi}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{o}{=}\PYG{n}{form}\PYG{o}{.}\PYG{n}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}dosya}\PYG{o}{=}\PYG{n}{form}\PYG{o}{.}\PYG{n}{i
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dosyaKaydet}\PYG{p}{(}\PYG{p}{)}
Bu basit işlevde, formda dosyanın patikası alınıp self.son_patika değişkenine aktarılıyor. Benzer şekilde
self.son_dosya değişkenine formdaki ids’si dosya_adi olan metin kutusundaki dosya adı aktarılıyor. Son
olarak dosyaKaydet() işlevi çağrılıyor. Şimdi de bu işlevi yazalım (build() den hemen önce):
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{dosyaKaydet}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{if} \PYG{o+ow}{not} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}dosya}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{hataGoster}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}
\PYG{k}{else}\PYG{p}{:}
\PYG{k}{try}\PYG{p}{:}
\PYG{n}{dosya\PYGZus{}tam\PYGZus{}isim} \PYG{o}{=} \PYG{n}{os}\PYG{o}{.}\PYG{n}{path}\PYG
\PYG{n}{F}\PYG{o}{=}\PYG{n+nb}{open}\PYG{p}{(}\PYG{n}{dosya\PYGZus{}tam\PYGZus{}isim}\PYG
\PYG{n}{F}\PYG{o}{.}\PYG{n}{write}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PY
\PYG{n}{F}\PYG{o}{.}\PYG{n}{close}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{except}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{hataGoster}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s
\PYG{o}{\PYGZpc{}} \PYG{n+nb}{str}\PYG{p}{(}\PYG{n}{sys}\PYG{o}{.}\PYG{n
Tahmin ettiğinizden daha karmaşık değilmi? Bir defa hataGoster() diye bir işlevin tanımlanması gerekiyor. Eğer
kullanıcı dosya adı yamamış ise (formdaki ids’si dosya_adi olan metin kutusu boş ise), kullanıcıya popup pencere
ile bunu bildirmeliyiz. Bunu hataGoster() işlevini tanımlayarak yapabiliriz. Eğer dosya ismi var ise, yazma işlemi gerçekleştirilecek. Bu ise biraz tehlikeli bir iş, öncelikle dosyanın tam adı oluşturuluyor (self.son_patika
ve self.son_dosya değişkenlerinin değerleri os.path.join() ile). Son olarak dosya açılıyor ve üzerine yazılıyor. Bunu try: bloğunda yaptık, çünkü dosya bir sebepten dolayı yazılamayabilir. Nasıl bir sebep olabilir ki?
Şöyle: disk dolu olabilir, dosyaya yazma yetkisi olmayabilir, klasöre yazma yetkisi olmayabilir, böyle bir disk olmayabilir .... Her ne sebeptenolursa olsun, dosya yazılamadığında programın kırılmayacak ve except: bloğu işletilerek
6.2. Farklı Kaydet
37
Kivy Mobil Programlama, Sürüm 0.1
dosyanın yazılamama sebebi kullanıcıla iletilecek. Bu da yine hataGoster() işlevi çağrılarak yapılıyor. Peki bu
hataGoster() işlevi kimin nesi? Kimsenin birşeyi değil! Sadece aşağıdaki kodlardan oluşan gariban bir işlev:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{hataGoster}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{hata}\P
\PYG{n}{icerik}\PYG{o}{=}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{hata}\PYG{p}{,} \
\PYG{n}{popup} \PYG{o}{=} \PYG{n}{Popup}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}}
\PYG{n}{popup}\PYG{o}{.}\PYG{n}{size\PYGZus{}hint} \PYG{o}{=} \PYG{p}{(}\PYG{l+m+mf}{7̇}\PYG{p}{,}
\PYG{n}{icerik}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}touch\PYGZus{}down}\PYG{o}{=}\
\PYG{n}{popup}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
Bu işlevi build() den hemen önce tanımlayabilirsiniz.
Aslında düzenlenen bir dosyayı bu şekilde doğrudan yazmak akıllı bir programcını yapacağı iş değildir. Eğer bir
nedenden dolayı dosya yazılamaz ise, program sonlanır ve kullanıcının önceki yeazdıkları da dahil olmak üzere kaybolur. Bu şekilde kaydedilirken bir problem çıkması durumunda çoğu zaman boş bir dosya elde edilir. Olası durumları
kontrol ettik, ancak birde kontrol edemediğimiz durumlar var. Öreğin tam yazma aşamasında, elektrik kesilirse! Bu
durumda kullanıcıya boş bir dosya verir bol küfür alırsınız. Tüm programlama dillerinde diske yazma işlemi doğrudan gerçekleşmez, belirli bir buffer büyüklüğü vardır bu dolduğunda diske yazılır daha sonra buffer’in tekrar dolması
beklenir (hızdan tasaffur, disk kullanımından tasarruf gibi nedenlerle). Bu nedenle dosya kapatılana kadar (close())
yazma işleminden emin olmazsınız [her harfi yazdıktan sonra flush() kullanmamışsanız :-)]. En iyisi önce dosyayı
geçici olarak yazmak, daha sonra dosya adını değiştirmektir. Örneğin:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{F}\PYG{o}{=}\PYG{n+nb}{open}\PYG{p}{(}\PYG{n}{dosya\PYGZus{}tam\PYGZus{}isim}\PYG{
\PYG{n}{F}\PYG{o}{.}\PYG{n}{write}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{
\PYG{n}{F}\PYG{o}{.}\PYG{n}{close}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{os}\PYG{o}{.}\PYG{n}{rename}\PYG{p}{(}\PYG{n}{dosya\PYGZus{}tam\PYGZus{}isim}\PYG{o}{+}\PYG{l
Burada da yine dikkat etmemiz gereken şey, dosya_tam_isim dosyasının yazılabilir olduğundan emin olmaktır.
Bunuda
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{os}\PYG{o}{.}\PYG{n}{access}\PYG{p}{(}\PYG{n}{dosya\PYGZus{}tam\PYGZus{}isim}\PYG{
ile kontrol edebilirsiniz. “Farklı Kaydet” bitti. Şimdi sıra geldi “Kaydet”e
6.3 Kaydet
Bu sandığınızdan daha kolay. Çünkü birçok işi, “Farklı Kaydet”de yaptık. Öncelikle ana pencerede “Kaydet” düğmesinde tıklandığında bir işlev çağırmalıyız ve tüm işi bu işelve yaptırtmalıyız. Bunun için Liste 6.2‘deki 17. satırı
aşağıdaki gibi değiştirelim:
=
{}=
{}@default
=0=1=2=0=1=2on\PYGZus{}press: app.dosyaKaydetIslevi()
Şimdi de bu işlevi yazalım, build() den hemen önce şu şekilde tanımlayabiliriz:
38
Bölüm 6. Metin Düzenleyici
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{dosyaKaydetIslevi}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}dosya}\PYG{p}{:} \PYG{n+nb+bp}{self}
\PYG{k}{else}\PYG{p}{:} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{farkliKaydetDialog}\PYG{p}{(}\PYG{p}
Burada dikkat ederseniz, öncelikle dosya adının olup olmadığına bakılıyor. Dosya adı var ise doğrudak
dosyaKaydet() işlevi çağrılıyor. Bunu daha önce yazmıştık. Dosya adı yok ise, farkliKaydetDialog()
işlevi çağrılıyor. Bunu da “Farklı Kaydet” kesitinde yazmıştık. Çok kolaymış değil mi?
6.4 Aç
Var olan bir dosyayı açmak için kullanacağımız bu düğme, eğer dikkatli olmazsak başımıza iş açabilir. Sebep? Eğer
düzenlenmekte olan bir dosya kaydedilmeden, başka bir dosya açılmaya kalkışılırsa ve siz bunu kullanıcya bildirmemişseniz, bu durumda istenmedik laflar işitebilirsiniz (merak etmeyin, nasıl olas programı kullanan uzakta olacağından
duymazsınız). İşitmeseniz bile buna dikkat etmek iyi bir programcı olduğunuzu gösterir. Peki bir metnin değiştiğini ve
kaydedildiğini nasıl anlayacağız? Bunu bizim için yapacak bir kimse yok. Bu nedenle başımızın çaresine bakmalıyız.
Önce metnin değişip değişmediğini bilmemiz gerekiyor, bunu tanımlayacağımız self.metin_degisti değişkeni
ile takip edebiliriz. O halde build() işlevi altına aşağıdaki satırları ekleyelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{o}{=}\PYG{n+nb+bp}{False}
Değerini False yaptık çünkü başlangıçta bir netnin içeriği değişmemiştir. Metin değiştikçe bunun değerini True,
kaydettikçe değerini False yapmalıyız. Önce kaydettiğimizde değerin False olması için dosyaKaydet() işlevindeki F.close() satırından hemen sonra şu satırı eklemeliyiz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{o}{=}\PYG{n+nb+bp}{False}
Bu tamam, peki metnin değiştiğini nasıl anlayacağız? Bunu bize Kivy söyleyebilir. TextInput perçacığının
text‘ine bir işlev bağlarsak, metin değiştikçe bu işlev çağrılır. O halde build() işlevinin altına aşağıdaki satırları eklemeliyiz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{metin}\P
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilkAcilis}\PYG{o}{=}\PYG{n+nb+bp}{True}
Buradaki self.ilkAcilis değişkeni, programın ilk açlıp açılmadığını takip etmek için gereklidir. Çünkü
TextInput nesnesi oluşturulur oluşturulmaz self.metinDegisti işlevi çağrılır. Buda programın ilk
açılıp açılmadığına göre self.metin_degisti değişkeninin değerini değiştirmelidir. Bize gerekli olan
metinDegisti() işlevini build() den hemen önce şöyle tanımlayabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{metinDegisti}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilkAcilis}\PYG{p}{:} \PYG{n+nb+bp}{self}\PYG{o}{
\PYG{k}{else}\PYG{p}{:} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{o}{=}\PYG
6.4. Aç
39
Kivy Mobil Programlama, Sürüm 0.1
Eğer programımız ilk açılışta bu işlev çağrılıyorsa, if self.ilkAcilis değişkeninin değeri False yapılıyor,
sonraki çağrılışlarda (metin girişi yapılır veya dosya okunursa), self.metin_degisti değişkeninin değeri True
yapılıyor.
Şu ana kadar dosya açma ile ilgili birşey yapmadık, sadece metnin değişip değişmediğini takip ettik. Öncelikle dosya açılma işlemini tıpkı “Kaydet”de olduğu gibi, bir dizin tarayıcı oluşturmamız gerekiyor. Bunu yine
FileChooserListView ile yapabiliriz. Bunun için bir form ve bu formu oluşturacak kv kodlarına ihtiyacımız
var. metinduzenleyici.kv dosyasına aşağıdaki kodu ekleyin:
Liste 6.4: dosyaAcForm
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}dosyaAcForm\PYGZgt{}:
title: \PYGZdq{}Dosya Aç\PYGZdq{}
size\PYGZus{}hint: (.9, .9)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
FileChooserListView:
size\PYGZus{}hint\PYGZus{}y: 9
filters: [\PYGZsq{}*.*\PYGZsq{}]
path: app.son\PYGZus{}patika
id: dosya\PYGZus{}secim
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
Button:
text: \PYGZdq{}Aç\PYGZdq{}
on\PYGZus{}press: app.dosyaOku(dosya\PYGZus{}secim); root.dismiss()
Button:
text: \PYGZdq{}Vazgeç\PYGZdq{}
on\PYGZus{}press: root.dismiss()
Bu kv formunu kullanacak sınıfı tanımlamak gerekiyor. Bunu class metinDuzenleyici(App) satırından
önce aşağıdaki kodları ekleyerek yapabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{class} \PYG{n+nc}{dosyaAcForm}\PYG{p}{(}\PYG{n}{Popup}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
Şimdide “Aç” düğmesine tıklandığında çağrılacak olan işlevi kv dosyasında belirtelim. Bunun için Liste 6.2‘deki 14.
satırı aşağıdaki satırı şöyle değiştirelim:
=
{}=
{}@default
=0=1=2=0=1=2on\PYGZus{}press: app.dosyaAcIsleviDialog()
Şimdi de bu işlevi tanımlamak gerekiyor. build() den hemen önce işlevimizi şöyle tanımlayabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{dosyaAcIsleviDialog}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{hataGoster}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}
\PYG{k}{else}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dosyaAcDialog}\PYG{p}{(}\PYG{p}{)}
40
Bölüm 6. Metin Düzenleyici
Kivy Mobil Programlama, Sürüm 0.1
Bu işlev anladığınız üzere, dosyanın değişip değişmediğini kontrol ediyor. Eğer kaydedilmemişse, kaydetmesi için
uyarıyor. Kaydedilmiş ise, dosyaAcDialog() işlevini çağırıyor. O halde bu işevi de build() den hemen önce şu
şekilde tanımlayabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{dosyaAcDialog}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{form} \PYG{o}{=} \PYG{n}{dosyaAcForm}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{form}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
“Dosya Aç” formu açıldığında allta iki adet düğmemiz olacak. “Vazgeç” düğmesine tıklandığında form kapanacak.
“Aç” düğmesine tıklandığında ise, dosyaOku() işlevi çağrılıyor (metinduzenleyici.kv dosyasına eklediğimiz Liste 6.4‘deki 17. satır). Bu işlev oldukça basit, sadece seçilen dosyayı gidip okuması gerekiyor. Bunu da
build() den hemen önce aşağıdaki gibi tanımlayabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{dosyaOku}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{dosya\PYG
\PYG{k}{if} \PYG{n}{dosya\PYGZus{}secim}\PYG{o}{.}\PYG{n}{selection}\PYG{p}{:}
\PYG{k}{if} \PYG{n+nb}{len}\PYG{p}{(}\PYG{n}{dosya\PYGZus{}secim}\PYG{o}{.}\PYG{n}{selection}
\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{p}{,}\PYG{n+nb+bp}
\PYG{k}{try}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{met
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{met
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{o}{=}\PYG{n+nb+bp}{Fa
\PYG{k}{except}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{hataGoster}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG
\PYG{o}{\PYGZpc{}} \PYG{n+nb}{str}\PYG{p}{(}\PYG{n}{sys}\PYG{o}{.}\PYG{n
\PYG{k}{else}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{hataGoster}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}
Bu işlevdeki hemen herşeyi daha önce anlattık. Şimdi bir sorunumuz var (bitti mi ki?). Kullanıcı dosyayı düzenleyip yeni dosya açmak istediğinde sadece “Dosya kaydedilmedi. Önce kaydedin.” uyarısında bulunuyor. Oysa ki iyi
bir program dosyayı açmadan önce dosyanın değiştiğini uyarmalı ve kullanıcıya kaydedip kaydetmeyeceği ile ilgili
seçenek sunmalıdır. Bunun için yeni bir form tasarlamalıyız. Bu form sedece mevcut dosyanın kaydedilip kaydededilmemesini veya dosya açma işleminden vazgeçilmesini önermelidir. Böyle bir formu metinduzenleyici.kv
dosyasına aşağıdaki satırları ekleyerek tasarlayabiliriz:
Liste 6.5: dosyaKaydedilmediForm
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}dosyaKaydedilmediForm\PYGZgt{}:
title: \PYGZsq{}Mevcut Dosya Kaydedilmedi\PYGZsq{}
size\PYGZus{}hint: (.9, .9)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
size\PYGZus{}hint\PYGZus{}y: 9
text: \PYGZdq{}Çalıştığınız dosya kaydedilmedi
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
Button:
text: \PYGZdq{}Kaydet\PYGZdq{}
on\PYGZus{}press: app.dosyaKayedilmediKaydet(root)
Button:
6.4. Aç
41
Kivy Mobil Programlama, Sürüm 0.1
text: \PYGZdq{}Hayır\PYGZdq{}
on\PYGZus{}press: app.dosyaAcDialog(); root.dismiss()
Button:
text: \PYGZdq{}Vazgeç\PYGZdq{}
on\PYGZus{}press: root.dismiss()
Bu kv formunu kullanacak sınıfımızı class metinDuzenleyici(App) satırından önce aşağıdaki kodları ekleyerek yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{class} \PYG{n+nc}{dosyaKaydedilmediForm}\PYG{p}{(}\PYG{n}{Popup}\PYG{p}{)}\PYG{p}{
\PYG{k}{pass}
Peki bu form’u nerede çağıracağız? Bildiniz değilmi? Yoksa bilemediniz mi? Bilemeyenlere hemen söyleyeyim, dosyaAcIsleviDialog() işlevinde dosya açmak istediğinde “Dosya kaydedilmedi. Önce kaydedin.” uyarısında bulunuyorduk ya işte burada. Yani bu uyarının yapıldığı satırın yerine yazmalıyız. O halde
dosyaAcIsleviDialog() işlevini aşağıdaki gibi değiştirmeliyiz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{dosyaAcIsleviDialog}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{p}{:}
\PYG{n}{kaydedilmedi\PYGZus{}form} \PYG{o}{=} \PYG{n}{dosyaKaydedilmediForm}\PYG{p}{(}\PYG{p}
\PYG{n}{kaydedilmedi\PYGZus{}form}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{else}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dosyaAcDialog}\PYG{p}{(}\PYG{p}{)}
Dosyanın kaydedilmediği durumda dosya açmaya kalkışıldığında kullandığımız form’da kullanıcı “Kaydet” düğmesine tıklarsa dosyamızın kaydedilmesi için dosyaKayedilmediKaydet() işlevi çağrılmaktadır (Liste 6.5‘deki
15. satır). Bu işlevi build() den önce şu şekilde yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{dosyaKayedilmediKaydet}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PY
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}dosya}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dosyaKaydet}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{kok}\PYG{o}{.}\PYG{n}{dismiss}\PYG{p}{(}\PYG{p}{)}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{dosyaAcDialog}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{else}\PYG{p}{:}
\PYG{n}{kok}\PYG{o}{.}\PYG{n}{dismiss}\PYG{p}{(}\PYG{p}{)}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{hataGoster}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}
Burada benimde hoşalşamadığım ve birçok kullanıcı için de garip gelecek bir durum var. Eğer dosya daha önce
kaydedilmemiş ise, dosya adı (self.son_dosya değişkeninde saklanan) olmayacaktır ve bu durumda kullanıcıya “Farklı Kaydet”i kullanarak kaydetmesi önerisi sunulmaktadır. Oysa ki bunun yerine doğrudan farklı kaydet
dialoğu (farkliKaydetDialog()) çağrılmalıydı. Bu Kivy’de olmadı. Bunu yapabilmemiz için, bu diyalog açıldıktan sonra, programın kullanıcıdan tepki gelene kadar hiçbir iş yapmaması gerekir (diğer bir deyişle program akışı
durdurulmalıdır). Kivy’de ne yazıkki bu yok, en azından ben bilmiyorum.
6.5 Yeni
Kullanıcı bir dosya üzerinde çalışırken yeni bir dosya açmak isteyebilir. Bunun için ana penceremizin sağ alt tarafya
bunulnan “Yeni” düğmesine tıklayacak. Şimdi bunun üzerinde çalışalım. Yapacağımız işi şöyle özetleyebiliriz: ilk
42
Bölüm 6. Metin Düzenleyici
Kivy Mobil Programlama, Sürüm 0.1
olarak mevcut dosya değiştirilmiş ve henüz kaydedilmemiş ise, bunu kullanıcıya bildirmemiz gerekir, daha sonra yeni
dosya oluşturma işlemine geçeceğiz. Öncelikle ana penceredeki “Yeni” düğmesine tıklandığında çağrılacak olan işlevi
belirtmek için metinduzenleyici.kv dosyasındaki (Liste 6.2) 23. satırı şu şekilde değiştirmemiz gerekmektedir:
=
{}=
{}@default
=0=1=2=0=1=2on\PYGZus{}press: app.yeniDosyaAcIslevi()
Bu işlevi de build() den önce şu şekilde yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{yeniDosyaAcIslevi}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{p}{:}
\PYG{n}{form} \PYG{o}{=} \PYG{n}{yeniDosyaForm}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{form}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{else}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{yeniDosyaAc}\PYG{p}{(}\PYG{p}{)}
Burada metnin değişmesi durumumnda yeni bir dialog (form) açılacak. Bu forma ait kv kodlarını
metinduzenleyici.kv dosyasına aşağıdaki satırları ekleyerek oluşturabiliriz:
Liste 6.6: yeniDosyaForm
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}yeniDosyaForm\PYGZgt{}:
title: \PYGZsq{}Mevcut Dosya Kaydedilmedi\PYGZsq{}
size\PYGZus{}hint: (.8, .8)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
size\PYGZus{}hint\PYGZus{}y: 9
text: \PYGZdq{}Çalıştığınız dosya kaydedilmedi
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
Button:
text: \PYGZdq{}Vazgeç\PYGZdq{}
on\PYGZus{}press: root.dismiss()
Button:
text: \PYGZdq{}Evet\PYGZdq{}
on\PYGZus{}press: app.yeniDosyaAc(); root.dismiss()
Bu kv kodlarını kullanacak olan yeniDosyaForm() sınıfınıda class metinDuzenleyici(App) satırından
önce aşağıdaki kodları ekleyerek yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{class} \PYG{n+nc}{yeniDosyaForm}\PYG{p}{(}\PYG{n}{Popup}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
yeniDosyaForm’unda kullanıcı yeni dosya açmaktan vazgeçerse zaten form kapanıyor, eğer kaydetmek için “Evet”
düğmesine tıklarsa, yeniDosyaAc() işlevi çağrılıyor. Yeni dosya açma işlevini build() den hemen önce şöyle
yazabiliriz.
=
{}=
{}@default
6.5. Yeni
43
Kivy Mobil Programlama, Sürüm 0.1
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{yeniDosyaAc}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{metin}\PYG{o}{.
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}dosya}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+
En kolayı bu oldu sanırım, self.son_dosya değişkeninin değeri ile metin alanının değerini boş cümle yaparak
yeni dosyayı oluşturmuş olduk.
6.6 Çıkmadan Önce
Henüz bitmedi. Çıkmadan önce yapılacak işlerimiz var. Kullanıcı metni düzenlerken çıkmak isterse ne yapacağız?
Öncelikle, maobil cihazın “Geri” tuşuna basarak programdan çıkması engellenmeli ve çıkış kontrollü bir şekilde yapılmalıdır. “Geri” tuşuna basarak çıkmayı engellemek için programın başında bunu yapmak gerekiyor, yani daha
uygulamayı başlatmadan önce. Geri tuşu ile çıkışı engellemek için main.py programının ikinci ve üçüncü satırına
aşağıdaki kodları yazabilirsiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k+kn}{from} \PYG{n+nn}{kivy.config} \PYG{k+kn}{import} \PYG{n}{Config}
\PY
aslında Config modülü daha fazla iş yapabilmektedir. Burada sadece geri tuşu ile çıkmayı engellemek için kullandık,
bunu exit_on_escape parametresini False yaparak gerçekleştirmiş olduk. Windows ya da Linux’da pencere kapatma
düğmesi ile hala programdan çıkılıyor olmalı, bunu dikkate almayın çünkü nasıl olsa programımız mobil cihazlarda
çalışacak. Geri tuşu ile çıkmayı engelledik te, kullanıcı nasıl çıkacak? İsterseniz ana penceremizin sağ alt köşesine
küçük bir düğme koyalım ve bu düğmeye tıklandığında çıkışı gerçekleştirelim. Böylelikle çıkmak isteyen kullanıcı
bu tuşa basacak ve bir işlev çağrılacaktır. Bu işlevde istediğimizi kontrol edebiliriz. Çıkış düğmesini eklemek için
metinduzenleyici.kv dosyasının (Liste 6.2) ana pencere düzenini oluşturan metinDuzenleyici formunun
altındaki düğmeleri oluşturan BoxLayout altına aşağıdaki gibi bir düğme ekleyelim:
=
{}=
{}@default
=0=1=2=0=1=2Button:
id: cik\PYGZus{}dugmesi
size\PYGZus{}hint\PYGZus{}x: .15
background\PYGZus{}color: ( 1, 1)
on\PYGZus{}press: app.cik()
Dikkat etmişseniz, oldukça küçük bir düğme (%15 boyutunda) ve arka plan rengi yeşil olarak görünecek. Bir düğmenin arka plan rengi ni background_color özelliği ile ayarlayabiliyoruz. Bu özellik, diğer Kivy renk tanımlarında da
kullanılabileceği gibi, bir tüp (isterseniz bir liste) alır. Bu tüpün 4 elemanı olacaktır. Bu tüp ile rengi şöyle belirliyoruz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{p}{(}\PYG{n}{R}\PYG{p}{,} \PYG{n}{G}\PYG{p}{,} \PYG{n}{B}\PYG{p}{,} \PYG{n}{T}\PYG{p}
Buradaki harfleri anlamları şöyledir:
R: Kırmızı, G: Yeşil, B:Mavi
Renk oranlarını belirtmektedir. değerleri 0 ile 1 arasındadır. Bildiğimiz standart RGB ile aynı ancak 1 sayısı 255’e karşılık gelmektedir. En sondaki T Saydamlığı belirtmektedir. Bu değere 1 girerseniz tam katı (kesif, opak), 0 girerseniz
tam saydam olur.
Tekrar dönelim düğmemize, akrka plan rengini neden yeşil yaptık? Çünkü yeşil doğa ve orman rengi değil mi? :-)
Elbette bunun için değil, düğme yeşil olduğunda çıkış serbest olacak, kırmızı olduğunda metin değiştirilmiş fakat
44
Bölüm 6. Metin Düzenleyici
Kivy Mobil Programlama, Sürüm 0.1
kaydedilmemiş olacak. O halde programımız içerisinde
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{o}{=}\PYG{n+nb+bp}{False}
satırının olduğu her yerde aşağıdaki satırı ekleyerek düğmeinin yeşil renkli olmasını sağlayacağız:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{cik\PYGZ
Peki ne zaman kırmızı yapacağız? self.metin_degisti değişkeninin değerinin True olduğu yerlerde. Bunu da
programımız içerisindeki
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{o}{=}\PYG{n+nb+bp}{True}
satırının olduğu her yerde aşağıdaki satırı da eklemeliyiz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{cik\PYGZ
Bu satırları yazmayı ben başarabildim, eminim (aslında Mustafa’yım da sözün gelişi) sizde yapabileceksiniz. Çık
düğmesinin yeşile dönmesi gereken bir yer daha kaldı: yeniDosyaAc() işlevi. Bu işlevin en sonuna da aşağıdaki satırı
eklemeliyiz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{cik\PYGZ
Şimdi programınızı çalıştırın ve düğmenin rengini takip edi. Program açılışta yeşil renki çık düğmesi ile başlayacak.
Ne zaman metin yazarsanız, renk kırmızıya dönecek. Metni kaydettiğinizde tekrar yeşile dönecek. Ancak henüz çık
düğmesi işe yaramıyor çünkü düğmeye tıklandığında çağrılacak olan app.cik() işlevini yamadık. Önce bu düğmenin nasıl davranacağını düşleyelim. Bir defa metin değişmiş ise, programdan çıkmadan önce kaydedilip kaydedilmeyeceğini sormalı. O zaman bir tane form oluşturmalıyız ve bunu sormalıyız. metinduzenleyici.kv dosyasına
aşağıdaki gibi bir form ekleyelim:
Liste 6.7: cikmadanOnceForm
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}cikmadanOnceForm\PYGZgt{}:
title: \PYGZsq{}Mevcut Dosya Kaydedilmedi\PYGZsq{}
size\PYGZus{}hint: (.8, .8)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
size\PYGZus{}hint\PYGZus{}y: 9
text: \PYGZdq{}Çalıştığınız dosya kaydedilmedi
BoxLayout:
6.6. Çıkmadan Önce
45
Kivy Mobil Programlama, Sürüm 0.1
size\PYGZus{}hint\PYGZus{}y: 1
text: \PYGZdq{}Vazgeç\PYGZdq{}
on\PYGZus{}press: root.dismiss()
Button:
text: \PYGZdq{}Yinede Çık\PYGZdq{}
on\PYGZus{}press: app.stop()
Button:
Bu form’da bilmediğiömiz tek şey stop() işlevidir. Bu işlev uygulamadan çıkma işlemini gerçekleştirir. Bu formu kullanacak sınıfımızı da class metinDuzenleyici(App) satırından önce aşağıdaki kodları ekleyerek yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{class} \PYG{n+nc}{cikmadanOnceForm}\PYG{p}{(}\PYG{n}{Popup}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
Son olarak cik() işlevini yazalım. build()‘den hemen önce aşağıdaki satırları yazalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{cik}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{metin\PYGZus{}degisti}\PYG{p}{:}
\PYG{n}{kaydedilmedi\PYGZus{}form} \PYG{o}{=} \PYG{n}{cikmadanOnceForm}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{kaydedilmedi\PYGZus{}form}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{else}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{stop}\PYG{p}{(}\PYG{p}{)}
Programımız artık temel ihtiyaçları karşılayacak düzeye geldi. Peki bitti mi? Haaayııır. Neler kaldı? Hayal etmenin
sınırı yok. Örneğin son açılan dosyaların listesi, program açıldığında en çalışılan dosyanın otomatik açılması, kelime
bulma ve değiştirme ... Başka ? Bir de kahve yapsın, yemek istemiyoruz :-)
Anlattıklarımızı takip edemediyseniz, yada ben yaptıklarımı gözden kaçırıp eksik yazmışsam, bu bölümde anlattıklarımı yaptığım dosyaları şu adreslerden alabilirsiniz:
main.py: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/metinDuzenleyici/6/main.py
metinduzenleyici.kv: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/metinDuzenleyici/6/metinduzenleyici.kv
46
Bölüm 6. Metin Düzenleyici
BÖLÜM 7
Paketleme
Bu bölümde hazırlanan Kivy programının Android paketi haline getirilmesi anlatılacaktır.
7.1 Buildozer Kurulumu
Kivy programlarını paketlemenin en kolay yolu Buildozer kullanmaktır. Ne yazıkki Buildozer şimdilik sadece Linux’ta
çalışmaktadır. Windows kullanıcıları için VirtualBox üzerinde Sanal Linux Makina disk görüntüsü hazırlanmıştır.
Windows kullanıcıları belkide çoğu Linux kullanıcıları Sanal Linux Makina bölümünde anlatılanları yapabilirler.
Burada sadece Debian Jessie’de (8.3) nasıl kurulacağını anlatacağız. Sisteminizde git kurulu değilse:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZsh{}} apt\PYGZhy{}get install git
Yazılım havuzundan indirelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZsh{}} git clone https://github.com/kivy/buildozer.git
Kurulumu gerçekleştirelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZsh{}} \PYG{n+nb}{cd} buildozer
\PYG{g+gp}{\PYGZsh{}} python setup.py install
Eğer sisteminizde eksik paket var ise, size hangilerinin eksik olduğu bildirilecektir. Bu kurulum yeni kurulmuş Debian
Jessie’de (8.3) de denenmiştir. İleriki zamanlarda buildozer debian paketi çıkarsa daha kolay kurulum gerçekleştirilebilir.
Muhtemelen sisteminizde zlib1g-dev ve Cython kurulu olmayacak:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZsh{}} apt\PYGZhy{}get install zlib1g\PYGZhy{}dev
\PYG{g+gp}{\PYGZsh{}} apt\PYGZhy{}get install cython
Henüz Java derleyicisini kurmamış iseniz:
47
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZsh{}} apt\PYGZhy{}get install gcj\PYGZhy{}jdk
Buildozer’in paketleyebilmesi için 32 bit kütüphanelere ihtiyacı olacak. Şu şekilde kurabilirsiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZsh{}} dpkg \PYGZhy{}\PYGZhy{}add\PYGZhy{}architecture i386
\PYG{g+gp}{\PYGZsh{}} apt\PYGZhy{}get update
\PYG{g+gp}{\PYGZsh{}} apt\PYGZhy{}get install build\PYGZhy{}essential ccache lib32z1 libncurses5:i386
Tüm bu anlattıklarımı, VirtualBox üzerinde bir sanal makinada yaptım ve disk görüntüsünü
kullanımınız için aşağıdaki adrese koydum:
https://docs.google.com/uc?export=download&confirm=Ser1&id=0B3-o4L3R6zHvOE9OdDBCUmhLZ0E
Sizin tek yapmanız gereken yapmanız gereken Sanal Linux Makina‘de anlatılan VirtualBox’u kurmak.
7.2 Paket Derleme
Paket haline getirmek için önce başlatalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZdl{}} buildozer init
Daha sonra buildozer.spec dosyasını düzenleyelim. Ben sadece aşağıdaki değişiklikleri yaptım:
=
{}=
{}@default
=0=1=2=0=1=2\PYGZsh{} (str) Title of your application
title = Kivy Metin Duzenleyici
\PYGZsh{} (str) Package name
package.name = kiviymetinduzenleyici
Şimdi de sıra paketlemeye geldi:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZdl{}} buildozer android release
Şu şekilde başlaması gerekiyor:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{c+c1}{\PYGZsh{} Check configuration tokens}
\PYG{c+c1}{\PYGZsh{} Ensure build layout}
\PYG{c+c1}{\PYGZsh{} Check configuration tokens}
\PYG{c+c1}{\PYGZsh{} Preparing build}
\PYG{c+c1}{\PYGZsh{} Check requirements for android}
48
Bölüm 7. Paketleme
Kivy Mobil Programlama, Sürüm 0.1
\PYG{c+c1}{\PYGZsh{} Install platform}
\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}
İlk kez paketleme yapıyorsanız, ANT, SDK, NDK indirilecektir. Lütfen sabırlı olun. Daha sonra paketleme işlemi
yapılacaktır. Benim sanal makinamda bu işlem 10 dakikadan fazla sürmektedir. Şu şekilde sonlanması gerekir:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{c+c1}{\PYGZsh{} Android packages installation done.}
\PYG{c+c1}{\PYGZsh{} Check application requirements}
\PYG{c+c1}{\PYGZsh{} Check garden requirements}
\PYG{c+c1}{\PYGZsh{} Compile platform}
\PYG{c+c1}{\PYGZsh{} Distribution compiled.}
\PYG{c+c1}{\PYGZsh{} Build the application \PYGZsh{}1}
\PYG{c+c1}{\PYGZsh{} Package the application}
\PYG{c+c1}{\PYGZsh{} Android packaging done!}
\PYG{c+c1}{\PYGZsh{} APK KivyMetinDuzenleyici\PYGZhy{}1̇\PYGZhy{}release\PYGZhy{}unsigned.apk availabl
Derlenen dosya, derlemeyi başlattığınız klasörün içerisinde oluşturulan bin klasörüne kaydedilmiştir. Bu dosyayı
Android cihaza kurmadan önce imzalamanız gerekmektedir.
7.3 İmzalama
Paketinizi kurmadan önce imzalamanız gerekir. Bunun en kolay yolu apk-signer kullanmaktdır. Programı indirdikten
sonra zip paketini açın çalıştırın. Tarafımdan hazırlanan Sanal Linux Makina kullanıyorsanız, masaüstünde apk-signer
simgesi üzerine tıklayın.
7.3.1 Anahtar Oluşturma
Önce anahtar oluşturacağız (Sanal Linux Makina kullananlar için kivy ev klasöründe bir tane anahtar mevcut). Programınız çalıştığında Key Generator sekmesinde olacaktır. Bu sekmede iken ilk yapacağınız anhtarınızı kaydedeceğiniz
dosyayı belirlemek. Bu amaçla [ Save as... ] düğmesine tıklayın. Anahtarınızı kaydedeceğiniz klasörü seçin (bizdeki
örnekte /home/kivy) ve dosya adını yazın (biz benim yazdık). Yaptıklarımız Şekil 7.1 görünmektedir.
Daha sonra gerekli bilgileri doldurun. Password ve Confirm alanlarına aynı parolayı girin (en az 8 karakter). Bizim örneğimizde kivy123 girdik. Bir Alias belirleyin, biz Kivy yaptık. Alias’ınız için yine parola (Alias password ve Confirm
alanlarına) girin. Biz yine kivy123 girdik. Bu parolaları unutmayın, çünkü bundan sonra imzalayacağınız her pakette
kullanacaksınız. Diğer alanları istediğiniz gibi doldurun. Şekil 7.1‘de oluşturduğumuz anahtar için bilgilerin girilmiş
hali görünmektedir.
Generete Keyfile düğmesine tıklayarak anahtarınızı oluşturun.
7.3.2 İmzalama
Anahtarınızı (aslına imzanız) oluşturduktan hemen sonra paketinizi imzalayabilirsiniz. Bunun için Signer sekmesine
geçin. Önce [ Load Keyfile... ] düğmesine tıklayarak, oluşturduğunuz anahtarı seçin. Eğer oluştruruken yukarıdaki
gibi benim yazmışsanız, ev dizininizde benim.keystroke dosyasını seçin. Bu imzanın parolasını Password alanına yazın. Bir Alias seçin (yukarıda Kivy yazdık) ve bunun parolasını Alias password alanına girin. [ Load target file...
] düğmesine tıklayın. Açılan pencerede imzalamak istediğiniz paketi seçin, biz Kivy Metin Düzenleyici’yi derlemiştik onu seçiyoruz (MetinDuzenleyici/bin/ KivyMetinDuzenleyici-0.1-release-unsigned.apk). Yaptıklarımız Şekil 7.3‘de
görünmektedir.
7.3. İmzalama
49
Kivy Mobil Programlama, Sürüm 0.1
Şekil 7.1: Anahtar Dosyası
50
Bölüm 7. Paketleme
Kivy Mobil Programlama, Sürüm 0.1
Şekil 7.2: Anahtar Oluşturma
Şekil 7.3: APK Paketini imzalama
7.3. İmzalama
51
Kivy Mobil Programlama, Sürüm 0.1
Son olarak Sign düğmesine tıklayın. Şimdi MetinDuzenleyici/bin/KivyMetinDuzenleyici-0.1-releaseSIGNED_UNALIGNED.apk dosyasını bir Android cihaza kurabilirsiniz.
7.4 Sanal Linux Makina
Windows kullanıcıları için Linux’u ve diğer paketleri kurmadan (epeyce zahmetli bir iş),
programlarını
apk
haline
getirebilecekleri
bir
sanal
makina
disk
görüntüsü
hazırlanmış
https://docs.google.com/uc?export=download&confirm=Ser1&id=0B3-o4L3R6zHvOE9OdDBCUmhLZ0E
adresine konulmuştur. Bu dosyayı indirin ve bir arşiv programı ile (örneğin winrar) masaüstüne açın.
Sanal makine disk görüntüsü Oracle VirtualBox 5.0.16 r105871 sürümü ile hazırlanmıştır. Kullanıcılar mutlaka bu
sürümü indirmelidir. Diğer sürümlerde windows-linux bağlantısı sağlanamayabilir ve ana makinanızın dosyalarına
erişiminiz olamayabilir.
7.4.1 VirtualBox kurulumu
https://www.virtualbox.org/wiki/Download_Old_Builds_5_0 adresinden 5.016 sürümünü indirin ve inen dosya üzerine çift tıklayın. Birkaç “Next” düğmesine tıkladıktan sonra “Install” düğmesine tıklayın. Size uyarı “Bu aygıt yazılımını ....” uyarısını verdiğinde “Yükle” düğmesine tıklayın.
7.4.2 Sanal Makina Oluşturma
Vitrualbox açıldığında yeni bir sanal Makine oluşturmak için sol üst köşedeki “Yeni” düğmesine tıklayın. Açılan
pencerede “Adı” alanına istediğiniz bir isim yazın, ben kivy yazmayı tercih ettim. Türü “Linux”, Sürüm “Debian
(32-bit)” seçin (Şekil 7.4‘de)
“İleri” düğmesine tıkladığınzda sanal makine için ayıracağınız belleği seçmeniz gerekmektedir. Her ne kadar 768MB
önerilse de, 1024MB’den daha fazla bir bellek ayırmaya çalışın. Ben genelde 1536MB (1.5GB) ayrımayı tercih ediyorum (Şekil 7.5‘de):
“İleri” düğmesine tıkladığınızda sanal makinanın kullanacağı disk görüntüsünü belirleyeceğiniz pencere gelecektir.
Burada “Var olan sanal bir sdabit disk dosyası kullan” seçeneğini seçip,=20pt=20pt@default=20pt=20pt@default simgesine tıklayın ve daha önce indirip açtığınız deb-i386.vdi dosyasını seçin (Şekil 7.6‘de):
“Oluştur” düğmesine tıkladığınızda sanal makinanız hazır olacaktır.
7.4.3 Paylaşım Açma
Makinanızı başlatmadan önce, Windows kolasörlerinize erişimi sağlayacak olan paylaşımıda yapmalısınız. Bu paylaşım sayesinde Windows makinanızda yazmış olduğunuz Kivy programlarına sanal Makine içerisinden erişebilecek
ve derleme işlemini yapabileceksiniz. Bunun için “Ayarlar” düğmesine tıklayın. Açılan pencerenin sol panelinden
“Paylaşılan Klasörler”i seçin. Sağ paneldeki=20pt=20pt@default=20pt=20pt@default simgesine tıklayarak yeni bir
paylaşım ekleme penceresi açın. Bu pencerede Klasör Yolu’ na sanal Makine ile paylaşmak istediğiniz klasörü seçin.
Ben masaüstümdeki kivy klasöürünü seçtim. Klasör Adı’nı “windows” olarak değiştirin. Eğer değiştirmez iseniz, sanal makinada paylaşımlar /media/sf_paylasimadi olarak bağlanacaktır. Hazırladığım disk görüntüsünde “windows” paylaşımını kivy kullanıcısının ev dizinine köprülediğimden Klasör Adını’nı “windows” olarak değiştirmenizde
fayda var. “Tamam” düğmesine tıklamadan önce “Otomatik-bağla” seçeneğini işaretlemeyi unutmayın (Şekil 7.7).
Sanal makinayı başlatmak için sola panledeki Makine ismi üzerine çift tıklayın. Makinanız bir süre sonra açılacaktır.
Açılan makinada kivy kullanıcısı oturum açmış durumundadır. root ve kivy kullanıcılarının parolaları kivy123 olarak
belirlenmiştir (masaüstündeki OKUBENI.txt dosyasında mevcut). Açılan sanal makineyi Şekil 7.8 ‘de görüyorsunuz.
şöyle
52
Bölüm 7. Paketleme
Kivy Mobil Programlama, Sürüm 0.1
Şekil 7.4: Makina mimarisi seçimi
Şekil 7.5: Sanal makinenin belleğini belirleme
7.4. Sanal Linux Makina
53
Kivy Mobil Programlama, Sürüm 0.1
Şekil 7.6: Sanal makinenin diskini belirleme
Örnek bir derleme yapalım. Bunun için ben metin düzenleyiciyi derlemek istiyorum. Bu nedenle aşağıdaki dosyaları
Windows makinamın masaüstündeki kivy klasörüne kaydettim (paylaştığım klasör).
https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/metinDuzenleyici/6/main.py
https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/metinDuzenleyici/6/metinduzenleyici.kv
Sanal makinede “Uçbirim Öykünücüsü” üzerine tıklayın. Bu size komut satırını açacaktır (şu Linux’çuların meşhur
siyah ekranı). Windows makinadan paylaşılan klasör sanal makinadaki kivy kullanıcısının ev dizinindeki windows
klasörüne köprilendiğinden, komut satırında aşağıdaki komutu işletin Önce kivy kullanıcısının ev dizininde deneme
isimli bir klasör oluşturalım ve derleyeceğimiz dosyaları buraya kopyalayalım (baştaki dolar $ işaretleri konulamyacaktır):
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZdl{}} mkdir deneme
\PYG{g+gp}{\PYGZdl{}} cp windows/main.py deneme
\PYG{g+gp}{\PYGZdl{}} cp windows/metinduzenleyici.kv deneme
Bu klasöre geçiş yapalım ve buildozer’i başlatalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZdl{}} \PYG{n+nb}{cd} deneme/
\PYG{g+gp}{\PYGZdl{}} buildozer init
buildozer.spec dosyasını düzenlemek için komut satırında aşağıdaki komutu işletin:
54
Bölüm 7. Paketleme
Kivy Mobil Programlama, Sürüm 0.1
Şekil 7.7: Sanal makine için paylaşım açma
7.4. Sanal Linux Makina
55
Kivy Mobil Programlama, Sürüm 0.1
Şekil 7.8: Linux Sanal Makine
56
Bölüm 7. Paketleme
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZdl{}} mcedit buildozer.spec
Deneme derlemesi için sadece aşağıdaki değişiklikleri yapın
=
{}=
{}@default
=0=1=2=0=1=2\PYGZsh{} (str) Title of your application
title = Kivy Metin Duzenleyici
\PYGZsh{} (str) Package name
package.name = kiviymetinduzenleyici
kaydetmek için klavyeden F2 tuşuna çıkmak için F10 tuşuna basın. Derlemek için komut satırından aşağıdaki komutu
çalıştırın.
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZdl{}} buildozer android release
şu şekilde başlaması gerekiyor:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{c+c1}{\PYGZsh{} Check configuration tokens}
\PYG{c+c1}{\PYGZsh{} Ensure build layout}
\PYG{c+c1}{\PYGZsh{} Check configuration tokens}
\PYG{c+c1}{\PYGZsh{} Preparing build}
\PYG{c+c1}{\PYGZsh{} Check requirements for android}
\PYG{c+c1}{\PYGZsh{} Install platform}
\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}
Buradan sonrasını Paket Derleme ‘den takip edebilirsiniz. Derlenen dosya, derlemeyi başlattığınız klasörün içerisinde oluşturulan bin klasörüne kaydedilmiştir. Bizi,m örneğimizde kivy kullanıcısının ev klasöründe bulunan
deneme/bin klasöründe olacaktır.
Bu dosyayı Android cihaza kurmadan önce imzalamanız gerekmektedir. İmzaladıktan sonra sanal mekinenizin masaüstündeki “Ev” simgesine tıklayarak dosya yöneticisini çalıştırabilir ve imzalanmış apk dosyasını Windows makinenizden erişmek üzere ev klasörünüzdeki windows klasörüne kopyalayabilirsiniz.
7.4. Sanal Linux Makina
57
Kivy Mobil Programlama, Sürüm 0.1
58
Bölüm 7. Paketleme
BÖLÜM 8
Atlıkarınca ve Resim Gösterici
Atlı karınca dememizin nedeni “carousel” kelimesi İngilizce’de “atlıkarınca” anlamını taşıması, elbette bir de at yarışlarındaki gösteri turnuvasına denmekte, ancak “carousel” isminin neye dayanarak verildiğini bilmiyorum (merak
etmiyor da değilim, yoksa şu parklarda gördüğümz askıda dönen salıncaklardan mı geliyor acabağa). Bu “Carousel”
denen şey nedir? Cep telefonunuzu kullanırken, ekranı sağa sola (ya da üste alta) parmaklarınızın ucu ile kaydırıyorsunuz ya, işte o. Bu bölümde Corusel (atlıkarınca) kullanarak bir resim gösterici yapmayı planlıyoruz. Normalde bir
resim göstericisini atlıkarınca ile yapmak ne kadar mantıklı bilemiyorum. Çünkü tüm resimleri başta atlıkarıncaya
yüklüyorsunuz. Bu da sanırım bellek kullanımını artırır. Her neyse biz burada bu atlıkarıncayı nasıl kullanacağımızı
öğreneceğiz.
8.1 Atlıkarınca (Carousel)
Atlıkarınca, bir çeşit düzen gibi düşünülebilir. Bu düzen kendi çerisinde çeşitli sekemeleri bulunan ve her sekmenin kendi düzeni bulunan bir yapıdır. Sekmeler bir pencerede bulunmaz, kaydırılarak ulaşılırlar. Burada atlıkarınca
sekmelerine sadece etiket (sonraki kesimde resim) koyacağız, ancak herhengi bir düzen de koyabilirsiniz.
Önce atlıkarıncanın nasıl çalıştığını öğrenelim. Atlıkarınca Carousel nesnesi ile oluşturulur. İstenilen bir düzen
(tek bir etiket, tek bir resim ya da diğer düzenler) bu nesneye add_widget özelliği ile eklenir. Liste 8.1‘deki gibi
main.py dosyasını yazalım.
Liste 8.1: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.carousel} \PYG{k+kn}{import} \PYG{n}{Carousel}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k}{class} \PYG{n+nc}{atliKarinca}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{karinca} \PYG{o}{=} \PYG{n}{Carousel}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{for} \PYG{n}{i} \PYG{o+ow}{in} \PYG{n+nb}{range}\PYG{p}{(}\PYG{l+m+mi}{5}\PYG{p}{)}\P
\PYG{n}{karinca}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Label}\PYG{p}{(}\P
\PYG{k}{return} \PYG{n}{karinca}
\PYG{n}{atliKarinca}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
59
Kivy Mobil Programlama, Sürüm 0.1
Bu programı biraz açıklayalım: 10. satırda bir atlıkarınca nesnesi oluşturuluyor. Daha sonra bu karıncaya 5 adet etiket
ekleniyor. Her etiketin üzerinde “Karınca Sayfası: 0”, “Karınca Sayfası: 1” ... yazmaktadır. Programı çalıştırıp fare
ile sayfayı sola doğru itip bırakın. Bu size sonraki sayfayı görüntüleyecektir. Mobil cihazlarda, sayfayı parmağınız ile
sola doğru itmeniz yeterlidir. Atlıkarıncanın yönü ön tanımlı olarak sola doğrudur. İsterseniz bunu direction özelliği
(parametresi) ile değiştirebilirsiniz. Bu parametrenin (ya da özelliğin) alabileceği değerler şunlardır: right, left, top,
bottom. Sanırım bunları açıklamaya gerek yok. Programın çalışmış halini Şekil 8.1‘de görüyorsunuz.
Şekil 8.1: Atlıkarınca
8.2 Resim Gösterici
Atlıkarıncaya etiket yerine, resim grafik parçacığını eklersek, metin yerine resimleri göstermiş olur.
8.2.1 Bir Klasördeki Resimler
Atlıkarıncayı basit olarak, programın bulunduğu dizindeki resimleri gösterecek şekilde kullanmaya çalışalım. Daha
sonra programımızı geliştireceğimizden kv dilini kullanarak hazırlayalım. Öncelikle resimgosterici.kv dosyamızı Liste 8.2‘deki gibi yazalım.
Liste 8.2: resimgosterici.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
60
Bölüm 8. Atlıkarınca ve Resim Gösterici
Kivy Mobil Programlama, Sürüm 0.1
=0=1=2=0=1=2 \PYGZlt{}resimGosterici\PYGZgt{}:
orientation: \PYGZdq{}vertical\PYGZdq{}
Carousel:
size\PYGZus{}hint\PYGZus{}y: 9
Bo
id: karinca
Buarada anadüzenimizi BoxLayout yaptık çünkü ilerde düğmeler yerleştireceğiz. Onun dışında bilmediğiniz bir kod
bulunmuyor. Atlıkarıncayı 4. satırdaki Carousel ile olışturduk. Bu nesneye ulaşmak için id’sini karinca yaptık.
Bu kv dosyasını kullanıp, programın çalıştığı klasördeki png resimlerini gösterecek main.py programını da Liste
8.3‘deki gibi yazabiliriz.
Liste 8.3: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{import} \PYG{n+nn}{os}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.image} \PYG{k+kn}{import} \PYG{n}{Image}
\PYG{k}{class} \PYG{n+nc}{resimGosterici}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{o}{=}\PYG{n}{os}\PYG{o}{.}\PYG{n
\PYG{k}{for} \PYG{n}{dosya} \PYG{o+ow}{in} \PYG{n}{os}\PYG{o}{.}\PYG{n}{listdir}\PYG{p}{(}\PY
\PYG{k}{if} \PYG{n}{os}\PYG{o}{.}\PYG{n}{path}\PYG{o}{.}\PYG{n}{splitext}\PYG{p}{(}\PYG{n
\PYG{n}{resim}\PYG{o}{=}\PYG{n}{Image}\PYG{p}{(}\PYG{n}{source}\PYG{o}{=}\PYG{n}{dosy
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{kar
\PYG{n}{resimGosterici}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Bu programda os.listdir() ile bulunduğumuz klasördeki (os.getcwd() ile alınıyor) dosylara üzerinde bir
iterasyon yapılıyor (11. satır). İterasyon içerisinde os.path.splitext() ile dosyaların (dosya_adı, uzantisi) şeklinde ayrılıyor ve uzantısı .png olan dosyalardan bir resim nesnesi oluşturuluyor. Resim nesnesi Image sınıfı ile oluşturulur. Bu sınıfa source paramteresi ile oluşturulacak resmin tam dosya adı (yada programın çalıştığı klasördeki dosya
adı) verilir. Oluşturulan resim nesnesi atlıkarıncanın add_widget özelliği ile ekleniyor. Ben programın çalıştığı
klasöre Kivy, Android ve Python logolarını koydum (umarım telif haklarını ihlal etmemişimdir). Programı çalıştırıp
resmi sürüklerken ekran görüntüsünü aşağıdaki (Şekil 8.2) gibi aldım.
Bir klasördeki resimleri dosyaların uzantılarına bakarak belirlemek deyim yerinde ise amele işi (burada ameleleri
küçümsemek gibi bir niyetimin olmadığını belirteyim), çünkü onlarda resim formatı var. Bunun yerine bir dosyanın
resim olup olmadığını, Python’un imghdr modülünü kullanarak anlayabiliriz. Bu modülün what özelliği resim
dosyasının tipini döndürür. Dosya resim değil ise hiçbirşey döndürmez. O Halde programımızı Liste 8.4‘deki gibi
güncelleyebiliriz.
Liste 8.4: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{import} \PYG{n+nn}{os}\PYG{o}{,} \PYG{n+nn}{imghdr}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.image} \PYG{k+kn}{import} \PYG{n}{Image}
8.2. Resim Gösterici
61
Kivy Mobil Programlama, Sürüm 0.1
Şekil 8.2: Basit Resim Gösterici (kaydırırken)
\PYG{k}{class} \PYG{n+nc}{resimGosterici}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{o}{=}\PYG{n}{os}\PYG{o}{.}\PYG{n
\PYG{k}{for} \PYG{n}{dosya} \PYG{o+ow}{in} \PYG{n}{os}\PYG{o}{.}\PYG{n}{listdir}\PYG{p}{(}\PY
\PYG{k}{if} \PYG{n}{imghdr}\PYG{o}{.}\PYG{n}{what}\PYG{p}{(}\PYG{n}{dosya}\PYG{p}{)}\PYG{
\PYG{n}{resim}\PYG{o}{=}\PYG{n}{Image}\PYG{p}{(}\PYG{n}{source}\PYG{o}{=}\PYG{n}{dosy
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{kar
\PYG{n}{resimGosterici}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Programın 2. satırında imghdr modülünü içerdiğimize dikkat edin.
Atlıkarıncaya resimleri build() altında eklemek mantıklı olmayacaktır. Çünkü ilerde çeşitli yollarla resim ekleyeceğiz her seferinde aynı işlemleri yapmamız gerekecek. Bunun yerine bir işlev yazalım ve resimleri orada ekleyelim.
İşlevimiz kendisine bir liste halinde gelen dosyaları atlıkarıncaya eklesin. Eğer resimler programın çalıştığı dizin değil
de (muhtemel olmayacak) başka bir yerde ise o zaman resimlerin tam patikasını vermek gerekecek. Bunu Liste 8.5‘’de
17. satırda kolayca yaptık.
Liste 8.5: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{import} \PYG{n+nn}{os}\PYG{o}{,} \PYG{n+nn}{imghdr}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.image} \PYG{k+kn}{import} \PYG{n}{Image}
\PYG{k}{class} \PYG{n+nc}{resimGosterici}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
62
Bölüm 8. Atlıkarınca ve Resim Gösterici
Kivy Mobil Programlama, Sürüm 0.1
\PYG{k}{def} \PYG{n+nf}{resimleriEkle}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{dosyalar}\P
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{karinca}\PY
\PYG{k}{if} \PYG{n}{os}\PYG{o}{.}\PYG{n}{path}\PYG{o}{.}\PYG{n}{isfile}\PYG{p}{(}\PYG{n}{dosy
\PYG{k}{for} \PYG{n}{dosya} \PYG{o+ow}{in} \PYG{n}{dosyalar}\PYG{p}{:}
\PYG{k}{if} \PYG{n}{imghdr}\PYG{o}{.}\PYG{n}{what}\PYG{p}{(}\PYG{n}{dosya}\PYG{p}{)}\
\PYG{n}{resim}\PYG{o}{=}\PYG{n}{Image}\PYG{p}{(}\PYG{n}{source}\PYG{o}{=}\PYG{n}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{o}{=}\PYG{n}{os}\PYG{o}{.}\PYG{n
\PYG{n}{dosyalar}\PYG{o}{=}\PYG{p}{[} \PYG{n}{os}\PYG{o}{.}\PYG{n}{path}\PYG{o}{.}\PYG{n}{joi
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{resimleriEkle}\PYG{p}{(}\PYG{n}{dosyalar}\PYG{p}{)}
\PYG{n}{resimGosterici}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Burada resimleriEkle() işlevinde kullandığımız atlıkarıncanın clear_widgets özelliği, daha önce eklenmiş tüm
nesneleri (burada resimler) temizlemek içindir. Bu satırı yazmadığımız taktirde önceki resimler de görünecektir. Ayrıca, os.path.isfile(dosya) kontrolü ile, seçilen klasörde bir başka lat klasör var ise, buna ait resim tipi
kontrolünün yapılmamasını sağladık.
Burada 19. satırı şu şekilde de yazabilirdiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{dosyalar}\PYG{o}{=}\PYG{p}{[}\PYG{p}{]}
\PYG{k}{for} \PYG{n}{x} \PYG{o+ow}{in} \PYG{n}{os}\PYG{o}{.}\PYG{n}{listdir}\PYG{p}{(}\PYG{n+nb+bp}{s
\PYG{n}{dosyalar}\PYG{o}{.}\PYG{n}{append}\PYG{p}{(}\PYG{n}{os}\PYG{o}{.}\PYG{n}{path}\PYG{o}{.}\
Önceki yazdığımız daha kısa olmalı.
8.2.2 Klasörü Seçme
Resimler çoğu zaman, önceden belirlenen bir klasör yerine, kullanıcının programı çalıştırdıktan sonra seçeceği bir
klasörde bulunacaktır. Bunu daha önce Metin Düzenleyici ‘de yapmıştık. Bunun için FileChooserListView‘ i kullanabiliriz. Fakat burada bir değişiklik yapalım ve index:‘FileChooserIconView kullanalım. İkisinin de kullanımı benzer, sadece görüntüleri farklı. FileChooserIconView dosya ve klasörleri görüntülerken liste, değil simgelerle
göstermektedir. Bu grafik parçacığını kv dosyasındaki bir form içerisinde kullanacağız. İlk olarak Liste 8.2 daki
resimgosterici.kv dosyasına aşağıdaki kodları ekleyin:
Liste 8.6: acForm
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}acForm\PYGZgt{}:
size\PYGZus{}hint: (.9, .9)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
FileChooserIconView:
size\PYGZus{}hint\PYGZus{}y: 9
filters: [\PYGZsq{}*.*\PYGZsq{}]
path: app.son\PYGZus{}patika
multiselect: True
8.2. Resim Gösterici
id: dosya\PYGZus{}secim
63
Kivy Mobil Programlama, Sürüm 0.1
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
Button:
text: \PYGZdq{}Seçilenleri Aç\PYGZdq{}
on\PYGZus{}press: app.secilenResimler(root); root.dismiss()
Button:
text: \PYGZdq{}Tüm Resimler\PYGZdq{}
on\PYGZus{}press: app.tumResimler(root); root.dismiss()
Burada farklı olarak multiselect özelliğinin değerini True yaptığımızı görüyorsunuz. Bu, kullanıcının birden fazla
dosyayı seçebilmesine olanak tanıyacaktır. Bu kv formunu kullanacak sınıfı tanımlamak gerekiyor. Bunu class
resimGosterici(App) satırından önce aşağıdaki kodları ekleyerek yapabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{class} \PYG{n+nc}{acForm}\PYG{p}{(}\PYG{n}{Popup}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
main.py programında bu sınıfı tanımlamadan önce aşağıdaki gibi Popup‘ı içermeyi unutmayın.
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.popup} \PYG{k+kn}{import} \PYG{n}{Popup}
Yeni formumuzu açabilmek için ana pencerede bir düğme koymalıyız, ki bu formu açsın. Bunu
resimgosterici.kv dosyasındaki resimGosterici formunu aşağıdaki gibi düzenleyerek yapabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYGZlt{}resimGosterici\PYGZgt{}:
BoxLayout:
orientation: \PYGZdq{}vertical\PYGZdq{}
Carousel:
size\PYGZus{}hint\PYGZus{}y: 9
BoxLayout:
size\PYGZus{}hint\PYGZus{}y: 1
text: \PYGZdq{}Aç\PYGZdq{}
on\PYGZus{}press: app.klasorAc()
id: karinca
Button:
Buarada klasorAc() işlevi ile acForm‘u açacağız. İkinci bir BoxLayout eklememizin nedeni ilerde başka düğmeleri de koyacağımızdır. Önce düğmeye tıklandığında formun açılabilmesi için build() den önce aşağıdaki işlevi
yazalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{klasorAc}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{form}\PYG{o}{=}\PYG{n}{acForm}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{form}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
Ana penceredeki “Aç” düğmesine tıklandığında Şekil 8.3‘deki gibi açılacaktır.
Önce tüm resimleri gösterebilmesi için , tumResimler() işlevini yazalım. Aşağıdaki işlevi build() den hemen
önce yazın:
64
Bölüm 8. Atlıkarınca ve Resim Gösterici
Kivy Mobil Programlama, Sürüm 0.1
Şekil 8.3: Dosya veya Klasör Seçimi
8.2. Resim Gösterici
65
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{tumResimler}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{kok}\P
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{o}{=}\PYG{n}{kok}\PYG{o}{.}\PYG{n}{i
\PYG{n}{dosyalar}\PYG{o}{=}\PYG{p}{[} \PYG{n}{os}\PYG{o}{.}\PYG{n}{path}\PYG{o}{.}\PYG{n}{join}\P
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{resimleriEkle}\PYG{p}{(}\PYG{n}{dosyalar}\PYG{p}{)}
Sanırım bu işlevdeki her satır sizin için anlaşılır. Yaptığımız tek şey son_patika değişkenine,
FileChooserIconView nesnesinden dosya_secim.path değerini atamak oldu. Eğer bir resmi tüm tuvale genişletmek istiyorsanız, resim nesnesinin allow_stretch özelliğini True yapmalısınız. Bunu yaptığınızda en-boy oranı
yine de korunacaktır. En-boy oranının da tuval’e eşitlenmesiniz istiyorsanız resim nesnesinin keep_ratio özelliğini
False yapmanız gerekmektedir. Bunlar için resimleriEkle() işlevindeki resim=Image(source=dosya)
satırından sonra şu satırları ekleyebilirsiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{resim}\PYG{o}{.}\PYG{n}{allow\PYGZus{}stretch}\PYG{o}{=}\PYG{n+nb+bp}{True}
\PYG{n}{resim}\PYG{o}{.}\PYG{n}{keep\PYGZus{}ratio}\PYG{o}{=}\PYG{n+nb+bp}{False}
Bu satırları eklediğimizde açılan resimler tüm tuval’i kaplayacaktır. Şimdide sadece seçilen resimleri göstermek üzere
secilenResimler() işlevini yazalım. Aşağıdaki işlevi build() den hemen önce yazalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{secilenResimler}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{ko
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{son\PYGZus{}patika}\PYG{o}{=}\PYG{n}{kok}\PYG{o}{.}\PYG{n}{i
\PYG{n}{dosyalar}\PYG{o}{=}\PYG{n}{kok}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{dosya\PYGZus{}seci
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{resimleriEkle}\PYG{p}{(}\PYG{n}{dosyalar}\PYG{p}{)}
Öncekinden daha kolay oldu, sadece son_patika yı belirlemek ve dosyaları almak oldu. Dikkat edersenin seçilen
dosyalar ile patikayı birleştirmedik, çünkü FileChooser nesnesi seçilen dosyayı patikası ile birlikte verir.
Programımız burada bitti, ancak kullanıcların istekler sonsuzdur. Bir programı yazmaya başlarken sadece temel ihtiyaçları göz önünde bulundurarak başlarız. Sonra aklımıza gelen eklentileri ya da kullanıcıların uygulanabilir makul
isteklerini ekleriz. Şöyle bir şey aklımıza gelse “Slay gösterisi”. Gelin şimdi bunu yapalım.
8.3 Zamanlayıcı ve Slayt Gösterisi
Slayt gösterisini yapabilmek için, zamanlayıcı ya (timer) ihtiyacımız var. Neden mi? Eğer resimler arası geçiş zamanını
time.sleep() ile ayarlarsanız, döngü bitene kadar program ile etkileşim yapılamaz. Bu nedenle zamanlayıcıya
ihtiyacımız var. Zamanlayıcıyı program içerisinde çalışan bir saat olarak düşünebilirsiniz. Bu saat her tık atışında
bir işlevi çağırır ve sizde bu işlevde yapılması gerekenleri kodlarsınız. Öncelikle ekranın en altına slayt gösterisini
başlatıp durdurabileceğimiz bir düğme ekleyelim. Bunu kv dosyasındaki <resimGosterici> formunun altındaki
BoxLayout düzenine aşağıdaki satırları ekleyerek yapabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2Button:
text: \PYGZdq{}Slaytı Başlat\PYGZdq{}
on\PYGZus{}press: app.slaytGosterisi(root)
Eğer hiç resim yüklenmediyse, bu düğmeyi pasifleştirmek gerekir. Kivy’de bir nesneyi pasifleştirmek için disabled
özelliğine Treu ataması yaparız. Ön tanımlı olarak nesnelerin disabled özelliği False konumundadır. O halde
66
Bölüm 8. Atlıkarınca ve Resim Gösterici
Kivy Mobil Programlama, Sürüm 0.1
öncelikle build() işlevinin en sonuna aşağıdaki satırı ekleyelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{slyat\PY
Böylelikle, program başladığında atlıkarıncada hiç resim olmayacağından, diğme etkin olmayacaktır. Bir de,
resimleriEkle() işlevinin en altına aşağıdaki satırları eklemeliyiz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{slyat\PYGZus{}d
\PYG{k}{else}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{slyat\PYGZus{}d
Nedenini şöyle açıklayalım. Herhangi bir düğmeye tıklayarak, atlıkarıncaya resim eklenmişse,
self.root.ids.karinca.slides değeri None dan farklı olacaktır ve düğme etkinleşecektir aksi halde
düğme pasif olacaktır.
Slayt gösterisi için zamanlayıcıya ihtiyacımız olduğunu söyledik, bunun için kivy modüllerini içerdiğimiz satırların
sonuna şu satırı ekleyelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k+kn}{from} \PYG{n+nn}{kivy.clock} \PYG{k+kn}{import} \PYG{n}{Clock}
<resimGosterici> formuna eklediğimiz id si slyat_dugme olan düğmeye
slaytGosterisi() işlevi çağrılacaktır. Şim bunu build() den hemen önce şu şekilde yazalım:
tıklandığında
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{slaytGosterisi}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{kok
\PYG{k}{if} \PYG{n}{kok}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{slyat\PYGZus{}dugme}\PYG{o}{.}\PY
\PYG{n}{Clock}\PYG{o}{.}\PYG{n}{schedule\PYGZus{}interval}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o
\PYG{n}{kok}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{slyat\PYGZus{}dugme}\PYG{o}{.}\PYG{n}{tex
\PYG{k}{else}\PYG{p}{:}
\PYG{n}{Clock}\PYG{o}{.}\PYG{n}{unschedule}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{zam
\PYG{n}{kok}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{slyat\PYGZus{}dugme}\PYG{o}{.}\PYG{n}{tex
Bu işleve başlarken, slayt gösterisi devam ediyor mu etmiyor mu onu kontrol ederek başladık. Bunu slyat_dugme
nin üzerindeki metni kullanarak kontrol ettik. Eğer düğme metni “Slaytı Başlat” ise, slayt başlamamıştır ve bu blokta
slaytı başlatıyoruz. Slaytı başlatmak için saatin (Clock) tik atış aralığını veriyoruz. Bunu Clock nesnesinin schedule_interval özelliği ile yaparız. Zamanlayıcı şu şekilde başlatılır:
Clock.schedule_interval(islev, atis_zaman_araligi)
Burada islev her tık attığında çağrılacak işlevi ve zaman_araligi tik aralıklarını saniye cinsinden ifade etmektedir.
Programımızda her tık atışta zamanlayiciIslevi() çağrılacaktır. Tık aralıkları ise 1 saniye olarak verilmiştir.
Zamanlayıcı (daha doğrusu slayt gösterisi) başladıktan sonra, slyat_dugme nin üzerindeki metni “Slaytı Durdur”
olarak değiştiriyoruz. Böylelikle aynı düğme salytı hem başlatmak hem de durdurmak için kullanılıyor.
Zamanlayıcı şu şekilde durdurulur:
Clock.unschedule(islev)
Zamanlayıcı ayrı işlevleri çağırmak için planlanabilir (schedule edilebilir) ve her seferinde isev ile atis_zaman_araligi
farklı olabilir. Planlanmış bir zamanlayıcıyı durdurmak için unschedule özelleğini kullanıyoruz.
8.3. Zamanlayıcı ve Slayt Gösterisi
67
Kivy Mobil Programlama, Sürüm 0.1
Buradan anlaşılacağı gibi slayt gösterisini yapacak işlevin çağrılmasını durdurmak için (planı bozmak için):
Clock.unschedule(self.zamanlayiciIslevi) satırını kullandık ve hemen sonrasında slyat_dugme
nin üzerindeki metni “Slaytı Başlat” yaptık.
Şimdide salyat gösterini yapacak olan zamanlayiciIslevi() işlevini yazalım. Bu işlev zamanlayıcının her tik
atışında çağrılacaktır. Her çağrılışta atlı karıncanın bir sonraki slaytını göstermesi gerekir. Atlıkarıncanın sonraki slaytı
göstermesi için load_next işevini kullanırız (önceki için load_previous‘). Zamanlayıcı işlevini slaytGosterisi()
nden önce aşağıdaki gibi yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{zamanlayiciIslevi}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{karinca}\PYG{o}
Zamanlayıcı işlevi çağırırken ilk argüman olarak, iki tik atışltaki zaman aralığını verir (belki programcının bunu kullanmaya ihtiyacı olabilir), bunu işlevimizde za olarak aldık.
Slayt gösterisi bittiğinde (en son resme gelindiğinde), sonraki resim gösterileyemecektir ve sürekli aynı resimde atlam olacaktır. Eğer atlıkarıncanın sonsuz döngüde (sona geldiğinde tekrar başa sarma) çalışmasını istiyorsanız loop
özelliğini True yapmalısınız. Programımızda build() işlevinin başına aşağıdaki satırı ekleyerek sonsuz döngüye
sokmuş oluruz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{karinca}
Son durumda programımızın penceresi Şekil 8.4‘deki gibi açılacaktır.
Anlattıklarımızı takip edemediyseniz, yada ben yaptıklarımı gözden kaçırıp eksik yazmışsam, bu bölümde anlattıklarımı yaptığım dosyaları şu adreslerden alabilirsiniz:
main.py: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/resimGosterici/5/main.py
metinduzenleyici.kv: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/resimGosterici/5/resimgosterici.kv
8.4 Kronometre Uygulaması
Zamanlayıcı kullanarak bir kronometre yapınız. Kronometrede iki düğme bulunmalıdır: Başlat ve Sıfırla Başlat düğmesine tıklanınca kronomtere başlayacak ve üzerindeki metin Durdur olacaktır. Sıfırla düğmesine tıklanınca kronometre sıfırlanacaktır. Kronometre tıklama aralığı 0.1 saniye (1 salise) olacaktır. Etiketteki metnin büyüklüğünü 100
piksel yapınız. Bir etiketin yazıtipi büyüklüğünü font_size özelliği ile ayarlayabilirsiniz. Kronometre sayaç görüntüsü
dak:saniye.salise şeklinde olacaktır.
Kronometreniz çalıştığında Şekil 8.5‘deki gibi bir pencere olacaktır.
Çözüm:
main.py: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/resimGosterici/kronometre/main.py
kronometre.kv: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/resimGosterici/kronometre/kronometre.kv
68
Bölüm 8. Atlıkarınca ve Resim Gösterici
Kivy Mobil Programlama, Sürüm 0.1
Şekil 8.4: Slayt Gösterici
8.4. Kronometre Uygulaması
69
Kivy Mobil Programlama, Sürüm 0.1
Şekil 8.5: Kronometre
70
Bölüm 8. Atlıkarınca ve Resim Gösterici
BÖLÜM 9
Liste Görünümü ve Eylem Çubuğu
Bu bölümde Liste Görünümünü, Açılır Kutu (DropDown) ve Eylem Çubuğu’nu anlatacağız. Konuları anlatırken daha
önce geliştirdiğimiz uygulamalara eklentiler yaparak uygulamasını da göstereceğiz.
9.1 Liste Görünümü
Kivy’de listeler ve ilgili görünümler (adaptör, uyarlayıcı kullanarak), daha önce kullandığım GUI (GKA)’lardan biraz
farklı çalışıyor. Bu farklılık listelerin kullanımınız biraz zorşaltırmış gibi görünse de, bu ona listelerin daha esnek ve
kullanışlı olmasını sağlıyor. İlk olarak basit bir liste oluşturalım. Bu liste sadece verileri görüntülemek için kullanılacak, seçim yapılamayacak ve herhangi bir eylem tanımlanamayacaktır. Bir liste oluşturmak için ListView nesnesini
kullanırız. ListView nesnesinin en basit kullanımı paramtere olarak item_strings vermektir. Bu parametre Python
listesi helinde listelenecek olan elemanları alır. Programlamada dillerini listeleyecek bir programı Liste 9.1‘deki gibi
yazabiliriz.
Liste 9.1: listeGorunumu.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.listview} \PYG{k+kn}{import} \PYG{n}{ListView}
\PYG{k}{class} \PYG{n+nc}{basitListeUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{duzen}\PYG{o}{=}\PYG{n}{BoxLayout}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{programlama\PYGZus{}dilleri}\PYG{o}{=}\PYG{p}{[}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{P
\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Rexx}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{
\PYG{n}{liste} \PYG{o}{=} \PYG{n}{ListView}\PYG{p}{(}\PYG{n}{item\PYGZus{}strings}\PYG{o}{=}\
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{liste}\PYG{p}{)}
\PYG{k}{return} \PYG{n}{duzen}
\PYG{n}{basitListeUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
71
Kivy Mobil Programlama, Sürüm 0.1
Programı çalıştırdığımızda Şekil 9.1‘de görünen pencere açılacaktır.
Şekil 9.1: Liste Görünümü (Temel)
9.1.1 SimpleListAdapter Adaptörü Kullanımı
Liste görünümlerini değiştirmek ve işerliğe kavuşturmak için ListView nesnesine bir adaptör vermektir. Bu
adaptörlerden en basiti ise SimpleListAdapter nesnesidir. Bu adaptör sadece listelemek için kullanılır. Programlama dillerininin isismlerini gösteren programı bu adaptörü kullanarak tekrar yazmak istersek: Liste 9.2‘deki gibi
basitListe.py dosyasını hazırlamamız gerekcek.
Liste 9.2: basitListe.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.adapters.simplelistadapter} \PYG{k+kn}{import} \PYG{n}{SimpleListAda
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.listview} \PYG{k+kn}{import} \PYG{n}{ListView}
\PYG{k}{class} \PYG{n+nc}{basitListeUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{duzen}\PYG{o}{=}\PYG{n}{BoxLayout}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{programlama\PYGZus{}dilleri}\PYG{o}{=}\PYG{p}{[}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{P
\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Rexx}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{
\PYG{n}{basit\PYGZus{}liste\PYGZus{}adaptoru} \PYG{o}{=} \PYG{n}{SimpleListAdapter}\PYG{p}{(}
\PYG{n}{liste} \PYG{o}{=} \PYG{n}{ListView}\PYG{p}{(}\PYG{n}{adapter}\PYG{o}{=}\PYG{n}{basit\
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{liste}\PYG{p}{)}
\PYG{k}{return} \PYG{n}{duzen}
\PYG{n}{basitListeUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
72
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Şimdi bu programı açıklamaya çalışalım. Programda 14. satırdaki programlama_dilleri listesi basit bir Python
listesidir. Görüntülemek istediğimiz elemanları bu listeye yazabiliriz. Liste yerine tüp (tuple) kullanabilirsiniz. Liste
görünümünde kullanabileceğimiz en basit adaptörün SimpleListAdapter olduğunu söylemiştik. Bu adaptör sadece bir dizi elemanı ekranda görüntülemek için kullanılabilir. Herhangi bir seçim ya da eylem gerçekleştiremezsiniz.
Kullanımı oldukça basittir: paramatere olarak data (listelenecek elemanlar) ve cls (görüntüleme biçimi) alır. Görüntüleme biçimi basit olarak bir etiket (Label) ya da düğme (Button) olabilir. Biz yukarıda etiket (Label) kullandık.
İsterseniz aynı programı düpme (Button) ile tekrar çalıştırın. Program çalıştığında yine Şekil 9.1‘de görünen pencere
açılacaktır.
Şekil 9.2‘de resimde aynı programın, listedeki görüntüleme biçiminin (cls=Button) düğme (Button) hali görünmektedir.
Şekil 9.2: Basit Liste (Düğme)
Liste 9.2‘deki programı, c:\windows (Linux için /usr) klasöründeki dosya ve dizinleri gösterecek şekilde uyarlayınız. Linux için programınızın çalışmış hali Şekil 9.3‘deki gibi olacaktır.
Şekil 9.3: Dosya ve Klasörlerin Listelenmesi (Linux)
Çözüm:
basitListe-klasorler.py: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/listeEylem/programlar/1/basitListeklasorler.py
9.1. Liste Görünümü
73
Kivy Mobil Programlama, Sürüm 0.1
Sonraki konuya geçmeden önce listelerin kv dili ile nasıl hazırlanacağına bakalım. Liste 9.2‘deki programımızın
aynısını kv dili ile yazalım. Önce Python programını Liste 9.3‘deki gibi yazalım
Liste 9.3: basitListeKv.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k}{class} \PYG{n+nc}{basitListeUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
\PYG{n}{basitListeUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Sanırım bu program çok kolay oldu ve herhangi bir açıklamaya ihtiyacı yok. Bu program tarafından kullanılacak kv
dosyasını Liste 9.4‘de görüldüğü gibi yazabiliriz.
Liste 9.4: basitlisteuyg.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZsh{}:import Label kivy.uix.label.Label
\PYGZsh{}:import SimpleListAdapter kivy.adapters.simplelistadapter.SimpleListAdapter
\PYGZlt{}basitListeUyg\PYGZgt{}:
BoxLayout:
Label:
text: \PYGZdq{}Programlama Dilleri\PYGZdq{}
ListView:
id: listeci
adapter:
SimpleListAdapter(
data=[\PYGZdq{}Perl\PYGZdq{}, \PYGZdq{}PHP\PYGZdq{}, \PYGZdq{}Pure\PYGZdq{}, \PYGZdq{}Pyt
cls=Label)
Bu kv dosyasının ilk iki stırında Label ve SimpleListAdapter nesnelerini ilgili modüllerden nasıl içerdiğimizi
iyice inceleyiniz. Program içerisinden adaptöre ve adaptörün verilerine ulaşabilir, güncelleyebilirsiniz ve hatta başka
adaptör kullanabilirsiniz. Aşağıdaki kodu build() işlevinin altına yazarsanız, programlama dilleri listesine “Pascal”,
“C” ve “C++” nin de eklendiğini göreceksiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{for} \PYG{n}{pr} \PYG{o+ow}{in} \PYG{p}{[}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Pasc
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{listeci}\PYG{o}
9.1.2 ListAdapter Adaptörü Kullanımı
Listeler genellikle arasından birisni seçmek için kullanılır ve daha önce anlatılan basit liste görünümü oluşturmaktan
daha karmaşık veriye sahip olabilir. Bunları ListAdapter veya DictAdapter adaptörlerini kullanarak yapabili74
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
riz. Burada sadece ListAdapter anlatılacaktır.
Önce ListAdapter kullanımına bakalım. Daha önce söyledğimiz gibi ListView parçacığında adaptörler, veriyi içerir.
Bu veri ListAdapter için her biri birer sözlük olan Python Listesidir. Örneğin kitaplara ait veriyi ele alalım (not:
kitaplar rastgele seçilmiştir, seçimde herhangi bir tercih yoktur):
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{kitaplar}\PYG{o}{=}\PYG{p}{[} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p}{:
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p}{:
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p}{:
Burada kitaplar bildiğimiz bir Python listesi ve elemanları bildiğimiz Python sözlükleridir. Her sözlük adi,
yazarı ve yayinevi anahtarları ile bunlara ait birer değer içermektedir. kitaplar listesini olduğu gibi
Listadapter nesnesine veri seti olarak atayabiliriz. Peki kullanıcıya ne gösterilecek? Bunu ise bir işlev yadımı
ile belirleyebiliriz. Bu işeve argüman çevirici (arg_converter) diyoruz. Argüman çevirici kendisine gelen veriyi, listede
gösterilecek şekilde düzenler ve yine bir sözlük döndürür. Bu sözlükte bulunması gereken tek zorunlu anahtar text
dir. Bu anahtarın değeri kullanıcıya listede gösterilen metindir. İsterseniz gösterilecek olan liste elemanı (burada ListItemButton olacaktır) (liste düğmesi) ile ilgili görünümü değiştirebilirsiniz; örneğin boyutunu.
Şimdi bunları birleştirelim ve seçilebilir bir liste oluşturalım. Programımızı Liste 9.5‘deki gibi yazalım
Liste 9.5: kitaplar.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{n+nn}{kivy.uix.listview} \PYG{k+kn}{import} \PYG{n}{ListView}
\PYG{n+nn}{kivy.adapters.listadapter} \PYG{k+kn}{import} \PYG{n}{ListAdapter}
\PYG{n+nn}{kivy.uix.listview} \PYG{k+kn}{import} \PYG{n}{ListItemButton}
\PYG{k}{class} \PYG{n+nc}{kitaplarUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{argumanCevirici}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{satir}\PY
\PYG{k}{return} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{text}\PYG{l+s+s1}{\PYGZ
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{kitaplar}\PYG{o}{=}\PYG{p}{[} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{a
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\
\PYG{n}{liste\PYGZus{}adaptoru}\PYG{o}{=}\PYG{n}{ListAdapter}\PYG{p}{(}\PYG{n}{args\PYGZus{}c
\PYG{n}{data}\PYG{o}{=}\PYG{n}{kitaplar}\PYG{p}{,}
\PYG{n}{cls}\PYG{o}{=}\PYG{n}{ListItemButton}\PYG{p}{,}
\PYG{n}{allow\PYGZus{}empty\PYGZus{}selection}\PYG{o}{=}\PYG{n+nb+
\PYG{n}{listeGorunumu}\PYG{o}{=}\PYG{n}{ListView}\PYG{p}{(}\PYG{n}{adapter}\PYG{o}{=}\PYG{n}{
\PYG{k}{return} \PYG{n}{listeGorunumu}
\PYG{n}{kitaplarUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
9.1. Liste Görünümü
75
Kivy Mobil Programlama, Sürüm 0.1
Programımızı çalıştıracak olursak Şekil 9.4‘deki gibi bir pencere açılacaktır.
Şekil 9.4: Seçilebilir Kitap Listesi
ListAdapter nesnesi arg_converter işlevine (burada argumanCevirici) iki adet argüman gönderir. Bunlardan ilki gönderilen verinin veri setindeki (data parametresine atanan değer, burada kitaplar listesi) konumu
(indeksi) ikincisi ise, verinin kendisi. kitaplar listesinin her elemanı sıra ile bu işleve gönderilir. Bu işev yine
bir sözlük döndürür. Sözlük en az text anahtarına sahip olmalıdır. text anahtarının değeri kullanıcıya gösterilen metindir. Liste 9.5‘daki programda size_hint_y ve height anhatarlarını kullanarak listedeki düğmenin
(ListItemButton) boytunu 25 piksel yaptık. ListItemButton nesnesi ile oluşturulan düğmelerin seçilmiş ve
seçilmemiş olanların rengini de değiştirebilirsiniz. Bunları deselected_color ve selected_color anahtarları ile yapabilirsiniz. Örneğin Liste 9.5‘daki programda argumanCevirici() işlevini aşağıdaki gibi yazarsanız, seçilmiş olan
düğme rengi mor, seçilmemiş olan düğmelerin rengi ise sarı olacaktır:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{argumanCevirici}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{sa
\PYG{k}{return} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{text}\PYG{l+s+s1}{\PYGZsq{}
\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{size\PYGZus{}hint\PYGZus{}y}\PYG{l+s+s1}{\PYGZsq{}}\PY
\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{deselected\PYGZus{}color}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p
\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{selected\PYGZus{}color}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p}{
\PYG{p}{\PYGZcb{}}
Eğer kullanıcıya görüntülenecek olan düğme üzerindeki metinde, sadece kitap adı yerine yazarının da görünmesini
istiyorsanız, argumanCevirici() işlevini şu şekilde değiştirebilirsiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{argumanCevirici}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{sa
\PYG{k}{return} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{text}\PYG{l+s+s1}{\PYGZsq{}
\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{size\PYGZus{}hint\PYGZus{}y}\PYG{l+s+s1}{\PYGZsq{}}\PY
\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{deselected\PYGZus{}color}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p
\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{selected\PYGZus{}color}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p}{
\PYG{p}{\PYGZcb{}}
Programımızı bu işlev ile çalıştıracak olursak Şekil 9.5‘deki gibi bir pencere açılacaktır.
argumanCevirici() işlevi sadece iki argüman alır ve bir sözlük dündürür. Bu tür bir işelev ihityacınız var ise
bunu Python’nun muhteşem lambda ifadesi ile gerçekleştirebilirsiniz. lambda ifadesi kendisine gelen argümanları
birer parametreye aktarır ve bu parametreleri kullanarak bir sonuç döndürme işlevi sağlar. Örneğin kendisine gelen
sayıları toplayan bir işleve ihtiyacımız var ise:
76
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Şekil 9.5: Değiştirilmiş Kitap Listesi
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{topla}\PYG{p}{(}\PYG{n}{a}\PYG{p}{,}\PYG{n}{b}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{return} \PYG{n}{a}\PYG{o}{+}\PYG{n}{b}
yerine:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{topla}\PYG{o}{=}\PYG{k}{lambda} \PYG{n}{a}
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{topla}\PYG{p}{(}\PYG{l+m+mi}{5}\PYG{p}{,}\PYG{l+m+mi}
\PYG{g+go}{12}
şeklinde yazabiliriz. Bu bilgiler ışığında argumanCevirici() işlevini hiç yazmadan arg_cvonverter parametresine aşağıdaki gibi lambda ifadesini yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{liste\PYGZus{}adaptoru}\PYG{o}{=}\PYG{n}{ListAdapter}\PYG{p}{(}\PYG{n}{args\PYGZus
\PYG{n}{data}\PYG{o}{=}\PYG{n}{kitaplar}\PYG{p}{,}
\PYG{n}{cls}\PYG{o}{=}\PYG{n}{ListItemButton}\PYG{p}{,}
\PYG{n}{allow\PYGZus{}empty\PYGZus{}selection}\PYG{o}{=}\PYG{n+nb+bp}{Fals
ListAdapter parçacığında anlatmadığımız allow_empty_selection paramteresine False değerini verirseniz, listede mutlaka bir seçim yapılmış olması gerekir. Bu durumda seçim yapılmamış ise, veri setinin ilk elemanı otomatik
olarak seçili hale gelir. Eğer allow_empty_selection değerini True yaparsanız (ön tanımlı değeri budur), listede bir seçim yapma zorunluluğu olmaz.
Liste 9.5‘daki programı kv dili ile yazalım. Önce ana programı Liste 9.6‘daki gibi yazalım.
Liste 9.6: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k}{class} \PYG{n+nc}{kitaplarUyg}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
9.1. Liste Görünümü
77
Kivy Mobil Programlama, Sürüm 0.1
\PYG{k}{def} \PYG{n+nf}{argumanCevirici}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{satir}\PY
\PYG{k}{return} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{text}\PYG{l+s+s1}{\PYGZ
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{kitaplar}\PYG{o}{=}\PYG{p}{[} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{a
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG{l+s+s1}{\PYGZsq{}}\
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{kitaplar}\P
\PYG{n}{kitaplarUyg}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Sanırım bu programda herşey açık. kv dosyasını ise Liste 9.7‘daki gibi hazırladım:
Liste 9.7: kitaplaruyg.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZsh{}:import ListItemButton kivy.uix.listview.ListItemButton
\PYGZsh{}:import ListAdapter kivy.adapters.listadapter.ListAdapter
\PYGZlt{}kitaplarUyg\PYGZgt{}:
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
text: \PYGZdq{}Kitap Seçiniz\PYGZdq{}
size\PYGZus{}hint\PYGZus{}y: None
height: 3
canvas.before:
Color:
rgba: [ 1, 1]
Rectangle:
pos: self.pos
size: self.size
ListView:
id: kitaplar
adapter:
ListAdapter(args\PYGZus{}converter=app.argumanCevirici,
data=[],
cls=ListItemButton,
allow\PYGZus{}empty\PYGZus{}selection=False)
Bu dosyayı inceleyecek olursanız, etikette ilk defa (11. satırda) canvas.before parametresini kullanmış olduk. Ne
yazıkki Kivy geliştiricileri bir etiketin arka plan rengini değiştirebilmemiz için bir parametre koymamış. Bunun yerine
parçacık çizilmeden önce tuvalin (canvas) arka planını boyamamız gerekir. Bunu da şu satırlar ile yapıyoruz:
=
{}=
{}@default
=0=1=2=0=1=2canvas.before:
Color:
rgba: [ 1, 1]
Rectangle:
pos: self.pos
size: self.size
78
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
9.1.3 Seçimin Denetlenmesi
En azından ListAdapter kullanılan liste görünümlerinde bir seçim yapıldığında, bir eylem gerçekleştirilmek isteniyorsa adaptörün on_selection_change olayına bir işlev bağlamak gerekir. Liste 9.6‘daki programda seçilen seçilen
kitaba ait ayrıntıları açılır pencerede görüntülemek üzere build() işlevinin en altına şu satırı ekleyelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{kitaplar
Bir kitap seçildiğinde secim() işlevi çağrılacaktır. Bu işleve, adaptörün kendisi argüman olarak verilecektir. Bir
adaptörde seçilen maddeler ait ListItemButton nesneleri Python listesi halinde selection özelliğinden alınabilir
(unutmayın birden fazla seçime olanak sağlamak için adatörün selection_mode parametresinin değerini multiple
yapmalısınız). Seçilen maddelerin listedeki konumlarını ise ListItemButton nesnesinin index özelliği ile alabiliriz. O halde secim işlevini şu şekilde yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{secim}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p
\PYG{k}{if} \PYG{n}{nesne}\PYG{o}{.}\PYG{n}{selection}\PYG{p}{:}
\PYG{n}{secimID}\PYG{o}{=}\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{selection}\PYG{p}{[}\PYG{l+m+mi}{}\
\PYG{n}{secilenKitap}\PYG{o}{=}\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{data}\PYG{p}{[}\PYG{n}{secimID
\PYG{n}{icerik}\PYG{o}{=}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{
\PYG{n}{secilenKitap}\PYG{p}{[}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{adi}\PYG
\PYG{n}{secilenKitap}\PYG{p}{[}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{yazari}\
\PYG{n}{secilenKitap}\PYG{p}{[}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{yayinevi
\PYG{n}{popup} \PYG{o}{=} \PYG{n}{Popup}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PYG{l+s+s1}{\PYGZs
\PYG{n}{content}\PYG{o}{=}\PYG{n}{icerik}\PYG{p}{,}
\PYG{n}{size\PYGZus{}hint}\PYG{o}{=}\PYG{p}{(}\PYG{n+nb+bp}{None}\PYG{p}{,} \PY
\PYG{n}{icerik}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}touch\PYGZus{}down}\PYG{o}
\PYG{n}{popup}\PYG{o}{.}\PYG{n}{open}\PYG{p}{(}\PYG{p}{)}
Aşağıdaki satırları programınızın başına yazmayı unutmayın:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.popup} \PYG{k+kn}{import} \PYG{n}{Popup}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
Şu halde programımızı çalıştırıp bir kitap seçtiğimizde, bir popup açılacak ve burada kitap detayları görüntülecektir
(Şekil 9.6).
9.1.4 İl-İlçe-Mahalle Seçimi
Liste görünümü ile ilgili daha ayrıntılı bir örnek yapalım. Hemen birçok alışveriş sitesinde bulunduğunuz il ve ilçe
seçimi ile ilgili açılır listeler bulunur. Biz buna bir de mahalleyi ekleyeceğiz. Uygulamamız şöyle tasarlayalım:
1. Ana pencereyi dikey olarak üç parçaya bölelim. Bunun için 3 sütunlu bir ızgara pencere düzenine ihtiyacımız
olacak.
2. Birinci sütunda illeri gösterelim. Buranın illeri gösterdiğini kullanıcıya bildirmek için etiketten bir başlık oluşturalım ve metnine “İl Seçiniz” yazalım. Etiketin altında liste görünümünde tüm illeri sıralayalım
9.1. Liste Görünümü
79
Kivy Mobil Programlama, Sürüm 0.1
Şekil 9.6: Kitap ayrıntılarının görüntülenmesi
3. İkinci sütunda ilçeleri gösterelim. Buranın ilçeleri gösterdiğini kullanıcıya bildirmek için etiketten bir başlık
oluşturalım ve metnine “İlçe Seçiniz” yazalım. Birinci sütunda seçilen ile ait ilçeleri etiketin altında liste görünümünde sıralayalım.
4. Üçüncü sütunda semtleri gösterelim. Buranın semtleri gösterdiğini kullanıcıya bildirmek için etiketten bir başlık
oluşturalım ve metnine “Semt Seçiniz” yazalım. İkinci sütunda seçilen ilçeye ait semtleri etiketin altında liste
görünümünde sıralayalım.
Uygulamamazı yazmadan önce ülkemizin illeri, bu illerin ilçeleri ve her ilçenin semtlerinin listesi gerekli. Bunu teker teker elinizle yazabilirsiniz. Ya benim gibi da internette “İl-ilçe-Semt-Mahalle-PostaKodu” şeklinde aratırsanız,
muhtemelen birçok veritabanı bulacaksınız. Aramam sonucunda şu adreste:
http://daltinkurt.com/Yazi/227/Il-Ilce-Semt-Mahalle-Veritabanlari-ve-Uygulamasi.aspx
bir tane buldum. Orada birçok veritabanı biçiminde hazırlanmış biçimlerini mevcut. Ben xml biçimini kullanacağım.
Yerel kopyasını buradan edinebilirsiniz (bunun için Sn. Devrim Altınkurt’dan izin alınmıştır):
Il-ilce-Semt-Mahalle-PostaKodu.xml:
https://raw.githubusercontent.com/mbaser/kivytr/master/docs/programlar/listeEylem/programlar/3/Il-ilce-Semt-Mahalle-PostaKodu.xml
Il-ilce-Semt-Mahalle-PostaKodu.xml dosyası oldukça büyük (~10 MB). Bu kadar büyük bir veriyi xml
ile saklamak ve sonra onu okuyup ayırt etmek oldukça zaman alıcı bir işlem, bu kadar büyük bir veriyi en azında
SqLite veritabanı sisteminde saklamak daha iyi. Ancak biz sadece deneme programı yazacağız, hem böylece bir xml
dosyasını nasıl okuyacağınızı da öğrenmiş oluruz.
Bir xml dosyasını kullanabilmek için, öncelikle dosya yapısını bilmeniz gerekir. Onun için dosyayı firefox ile açıp
yapısını inceleyebiliriz (Metin düzenleyici ya da xml editörleri ile açmayı denemeyin, dosya çok büyük). Dosyayı
incelediğimzde veri gruplandırmasının yapılmadığını görüyoruz. Dosyanın yapısından anladığımız kadarı ile aşağıdaki
çıkarımları yapabiliriz:
İller <tbl_il> etiketlerinde iller mevcut. Her il için bir ID verilmiş (<il_id>), il isimleri ise <il_ad> etiketi
ile beirtilmiş.
İlçeler İlçelerimiz <tbl_ilce> etiketleri ile ayrılmış. Her ilçe için bir ID verilmiş (<ilce_id>). İlçenin hangi ile
ait olduğu ise <il_id> etiketi ile belirtilmiş. İlçe adı ise <ilce_ad> etiketinde.
80
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Semtler Her ilçenin semtleri <tbl_semt> etiketleri ile verilmiş. Bağlı olduğu ilçe <ilce_id>, semt adı ise
<semt_ad> etiketi ile verilmiş. Elbetteki ID’si mevcut ve <semt_id> etiketinin metninde bulunuyor.
xml Dosyasının yapısını öğrendiğimize göre bu dosyayı okuyup veriyi bizim için ayır edecek Python modülünü kullanmamız gerekir. Önce Python konsolunda bunu öğrenelim. Dosyayı bir klasöre indirin ve Python konsolundan aşağıdaki
satırşarı işletin:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k+kn}{from} \PYG{n+nn}{xml.etree} \PYG{k+kn}{
\PY
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{xmlKok} \PYG{o}{=} \PYG{n}{agac}\PYG{o}{.}\PYG{n}{get
Burada ikinci satırda dosya patikasını kullandığınız işletim sistemine göre doğru şekilde belirtiniz. Dosya çok büyük
olduğu için okunması donanımınızın durumuna göre birkaç saniye alabilir. Şimdi illerimizi bulalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{iller}\PYG{o}{=}\PYG{n}{xmlKok}\PYG{o}{.}\
Şimdi iller listesinde tüm illerimizi ait xml elemanları bulunacaktır. Bunları ekrana bastırmak için:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k}{for} \PYG{n}{il} \PYG{o+ow}{in} \PYG{n}{il
\PY
\PYG{g+gp}{...}
\PYG{g+go}{1 Adana}
\PYG{g+go}{2 Adıyaman}
\PYG{g+go}{3 Afyonkarahisar}
\PYG{g+go}{4 Ağrı}
\PYG{g+go}{5 Amasya}
\PYG{g+go}{6 Ankara}
\PYG{g+go}{7 Antalya}
\PYG{g+go}{8 Artvin}
\PYG{g+go}{9 Aydın}
\PYG{g+go}{1 Balıkesir}
\PYG{g+go}{.}
\PYG{g+go}{.}
\PYG{g+go}{.}
Burada il adının UTF-8 biçimli bir metin olduğunu biliyoruz. Python 2.x’de düzgün gösterilebilmesi için metnin
encode("utf-8") özelliğini kullanmamız gerekiyor. Bir döngüyü kullanarak istediğimiz şekilde liste oluşturmayı
daha önce anlatmıştık tekrarlayalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{sayi\PYGZus{}listesi}\PYG{o}{=}\PYG{p}{[}
\PY
\PYG{g+go}{[\PYGZsq{}Sayi\PYGZhy{}1\PYGZsq{}, \PYGZsq{}Sayi\PYGZhy{}2\PYGZsq{}, \PYGZsq{}Sayi\PYGZhy{
Bir liste içerisinde yazdığımız döngünün nasıl bir sonuç doğurduğunu gördük. Aynı listeyi şöyle de oluşturabilirdiniz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{sayi\PYGZus{}listesi}\PYG{o}{=}\PYG{p}{[}\
\PY
\PYG{g+gp}{... }
\PYG{n}{sayi\PYGZus{}listesi}\PYG{o}{.}\PYG{n}{append}\PYG{p}{(}\PYG{l+s+s2}{\PYG
\PYG{g+gp}{...}
9.1. Liste Görünümü
81
Kivy Mobil Programlama, Sürüm 0.1
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{sayi\PYGZus{}listesi}
\PYG{g+go}{[\PYGZsq{}Sayi\PYGZhy{}1\PYGZsq{}, \PYGZsq{}Sayi\PYGZhy{}2\PYGZsq{}, \PYGZsq{}Sayi\PYGZhy{
İlk yaptığımız daha kolay değil mi? Peki iller xml elemanlarını kullanarak, liste adaptörümüz için nasıl bir veri
listesi oluşturacağız? Bu soruyu şöyle cevaplayalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{iller\PYGZus{}veri} \PYG{o}{=} \PYG{p}{[}
\PY
\PYG{g+go}{
for il in iller}
\PYG{g+go}{
]}
Liste içindeki döngülerde if ifadesini de kullanabiliriz. Örneğin il_id si 10’dan küçük illerin listesini elde edelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{iller\PYGZus{}veri} \PYG{o}{=} \PYG{p}{[}
\PY
\PYG{g+go}{
for il in iller if int(il.find(\PYGZsq{}il\PYGZus{}id\PYGZsq{}).text) \
\PYG{g+go}{
]}
Bunları öğrendiğimize göre, liste görünümü bilgilerini de kullanarak programımızı yazabiliriz. Önce ana programı
Liste 9.8‘daki gibi yazalım.
Liste 9.8: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{xml.etree} \PYG{k+kn}{import} \PYG{n}{ElementTree}
\PYG{n}{agac} \PYG{o}{=} \PYG{n}{ElementTree}\PYG{o}{.}\PYG{n}{parse}\PYG{p}{(}\PYG{l+s+s1}{\PYGZsq{}
\PYG{n}{xmlKok} \PYG{o}{=} \PYG{n}{agac}\PYG{o}{.}\PYG{n}{getroot}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{class} \PYG{n+nc}{illerIlceler}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{argCevir}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{satir}\PYG{p}{,}
\PYG{k}{return} \PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{text}\PYG{l+s+s1}{\PYGZ
\PYG{k}{def} \PYG{n+nf}{ilSecim}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)}\
\PYG{k}{if} \PYG{n}{nesne}\PYG{o}{.}\PYG{n}{selection}\PYG{p}{:}
\PYG{n}{secim}\PYG{o}{=}\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{selection}\PYG{p}{[}\PYG{l+m+mi}{
\PYG{n}{ilId}\PYG{o}{=}\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{data}\PYG{p}{[}\PYG{n}{secim}\PYG{
\PYG{n}{ilceler}\PYG{o}{=}\PYG{n}{xmlKok}\PYG{o}{.}\PYG{n}{findall}\PYG{p}{(}\PYG{l+s+s1}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{ilceler
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{ilceId}\PYG
\PYG{k}{for} \PYG{n}{ilce} \PYG{o+ow}{in} \PYG{n}{ilceler} \PYG{k
\PYG{p}{]}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{ilceler
\PYG{k}{def} \PYG{n+nf}{ilceSecim}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)
\PYG{k}{if} \PYG{n}{nesne}\PYG{o}{.}\PYG{n}{selection}\PYG{p}{:}
\PYG{n}{secim}\PYG{o}{=}\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{selection}\PYG{p}{[}\PYG{l+m+mi}{
82
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
\PYG{n}{ilceId}\PYG{o}{=}\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{data}\PYG{p}{[}\PYG{n}{secim}\PY
\PYG{n}{semtler}\PYG{o}{=}\PYG{n}{xmlKok}\PYG{o}{.}\PYG{n}{findall}\PYG{p}{(}\PYG{l+s+s1}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{semtler
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{semtId}\PYG{l+s+s1}{\PY
\PYG{k}{for} \PYG{n}{semt} \PYG{o+ow}{in} \PYG{n}{semtler} \PYG{k}{if} \PYG{n
\PYG{p}{]}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{semtler
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{iller}\PYG{o}{=}\PYG{n}{xmlKok}\PYG{o}{.}\PYG{n}{findall}\PYG{p}{(}\PYG{l+s+s1}{\PYGZ
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{iller}\PYG{
\PYG{p}{\PYGZob{}}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{ilId}\PYG{l+s+s1}{\PYGZ
\PYG{k}{for} \PYG{n}{il} \PYG{o+ow}{in} \PYG{n}{iller}
\PYG{p}{]}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{iller}\PYG{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{ilceler}\PY
\PYG{n}{illerIlceler}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Sanırım burada bilmediğimiz tek şey bir liste görünümünün _trigger_reset_populate() özelliği. Bir liste
görnümünün elemanlarını değiştirdiğinizde, bunların ekrana yansıması için bu özelliği kullanmamız gerekiyor. İnternet tarayıcıda değişen sayfayı yenilemek için “F5” tuşuna basmak gibi.
kv dosyasını ise Liste 9.9‘daki gibi hazırladım:
Liste 9.9: illerilceler.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZsh{}:import ListItemButton kivy.uix.listview.ListItemButton
\P
\PYGZlt{}illerIlcelerUyg\PYGZgt{}:
GridLayout:
cols: 3
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
text: \PYGZdq{}İl Seçiniz\PYGZdq{}
size\PYGZus{}hint\PYGZus{}y: None
height: 3
canvas.before:
Color:
rgba: 1,
1
Rectangle:
pos: self.pos
size: self.size
ListView:
id: iller
adapter:
ListAdapter(args\PYGZus{}converter=app.argCevir,
data=[],
cls=ListItemButton,
9.1. Liste Görünümü
83
Kivy Mobil Programlama, Sürüm 0.1
allow\PYGZus{}empty\PYGZus{}selection=False)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
text: \PYGZdq{}İlçe Seçiniz\PYGZdq{}
size\PYGZus{}hint\PYGZus{}y: None
height: 3
canvas.before:
Color:
rgba: 1, 1
Rectangle:
pos: self.pos
size: self.size
ListView:
id: ilceler
adapter:
ListAdapter(args\PYGZus{}converter=app.argCevir,
data=[],
cls=ListItemButton,
allow\PYGZus{}empty\PYGZus{}selection=False)
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
Label:
text: \PYGZdq{}Semt Seçiniz\PYGZdq{}
size\PYGZus{}hint\PYGZus{}y: None
height: 3
canvas.before:
Color:
rgba:
1, 1
Rectangle:
pos: self.pos
size: self.size
ListView:
id: semtler
adapter:
ListAdapter(args\PYGZus{}converter=app.argCevir,
data=[],
cls=ListItemButton,
allow\PYGZus{}empty\PYGZus{}selection=False)
Bu programda her liste görnümü için yeni bir argüman çevirici yazmak yerine sadece bir tane yazdık. Bunun için
tüm liste adaptarlerinin, veri setini hazırlarken görüntülenecek metni (il, ilçe, semt) adlarını adi anahtarına koyduk.
Böylece liste gornümü ne olursa olsun, listede görüntülenecek metin adi anahtarında bulunduğundan sadece bir tane
argCevir() işlevi yazmak yeterli oldu.
Programı çalıştıracak olursanız Şekil 9.7 de görünen pencere açılacaktır.
Not:
Derleme yaparken (Paket Derleme kısmında anlatılan) buildozer in paketin içine
Il-ilce-Semt-Mahalle-PostaKodu.xml dosyasını koyması için source.include_exts seçeneğinin sonuna xml eklenemsi gerekir (tüm xml uzantılı dosyalar içerilecektir):
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{source}\PYG{o}{.}\PYG{n}{include\PYGZus{}exts} \PYG{o}{=} \PYG{n}{py}\PYG{p}{,}\PY
84
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Şekil 9.7: İle-ilçe-semt Seçimi
9.1. Liste Görünümü
85
Kivy Mobil Programlama, Sürüm 0.1
Benim anlatacaklarım bitti. Şimdi kod yazma sırası size. xml dosyasında her semte ait mahalelerde mevcut. Biz bunları
göstermedik. Programa mahalle seçimini de yapacağımız eklentileri yapın. Programınız çalıştığında Şekil 9.8 deki gibi
görünmeldir.
Şekil 9.8: İle-ilçe-semt-mahalle Seçimi
Çözüm:
main-mahalleler.py: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/listeEylem/programlar/3/mainmahalleler.py illerilcelermahaller.kv: https://github.com/mbaser/kivy-tr/blob/master/docs/programlar/listeEylem/programlar/3/illerilcele
9.2 Açılır Kutu
Liste görünümü ile açılır kutu (DropDown) benzer işler yapsa da, temel işleyiş mantığı olarak birbirinden farklıdır.
Liste görünümünde, verdiğimiz seçenekler (ister seçilebilir düğme, iseterse etiket üzerinde olsun) kullanıcıya doğrudan gösterilir. Açılır kutularda ise, kullanıcı kutuya tıkladıktan sonra seçenekler ortaya çıkar. Önce nasıl çalıştığını
öğrenelim, daha sonra yukarıdaki örneği açılır kutu ile tekrar yapalım.
Daha önce de belirttiğim gibi Kivy’de birçok şey, bildiğimiz masaüstü GUI (GKA)’lerden farklı bir yapıya sahip. Bir
açılır kutuyu oluşturmak için daha fazla emek harcamak gerekiyor. Örneğin bir web sayfasında açılır kutu oluşturmak
için <select> etiketi arasına seçenekleri (<option>) ard arda yazdıkmı işimiz tamamlanıyor. Ancak Kivy’de bu
kadar kolay değil. Bir açılır kutu oluşturduğunuzda bunu pendere düzeninde öyle istediğiniz yere koyamazsınız. Bu
açılır kutuyu göstermek için bir başka nesneye ihtiyacınız olacak. Örneğin bir düğme. Bu düğmeye tıklayıp bıraktığınızda (on_release olayı), açılır kutuyu görünür yapabilirsiniz. Aslında herhangi bir nesnenin herhangi bir olayına da
bağlayabilirsiniz. Biz bir düğmeye tıklanıp bırakıldığında açılır kutuyu göstereceğiz.
Açılır kutu nesnesi DropDown() ile oluşturulur. Açılır kutunun open() özelliği ile görünür hale getirilince, kendisine eklenmiş olan diğer nesneleri gösterecektir. Bu nesnelerden herhangi birisi bildiğiniz düğme (Button) ya da
etiket (Label) olabilir. Bunları toparlayacak olursak birkaç isimden oluşan bir açılır kutuyu şu şekilde oluşturabiliriz:
86
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{acilirkutu} \PYG{o}{=} \PYG{n}{DropDown}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{for} \PYG{n}{isim} \PYG{o+ow}{in} \PYG{p}{(} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Mustafa}\PYG
\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{isim}\PYG{p}{,} \
\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{dugme}\PYG{p}{)}
Gördüğünüz gibi, yaptığımız iş DropDown() nesnesine bildik düğmeleri ekledik. Peki bir düğme seçilince ne olacak? Programımızı yazarken bunu da eklemek durumundayız. Açılır kutuyu oluşturduk ancak, bu açılır kutunun
görünebilmesi için herhangi bir eyleme bağlamamız gerekir. Bir düğme oluşturalım (anadügme) ve bu düğmenin
on_release eylemine açılır kutunun open() özelliğini bağlayalım. Bu bilgiler ışığında Liste 9.10‘daki gibi bir
program yazalım.
Liste 9.10: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{n+nn}{kivy.uix.dropdown} \PYG{k+kn}{import} \PYG{n}{DropDown}
\PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k}{class} \PYG{n+nc}{acilirKutu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{secim}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)}\PY
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{select}\PYG{p}{(}\PYG{n}{ne
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{anadugme}\PYG{o}{.}\PYG{n}{text}\PYG{o}{=}\PYG{n}{nesne}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{duzen} \PYG{o}{=} \PYG{n}{BoxLayout}\PYG{p}{(}\PYG{p}{)}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{anadugme} \PYG{o}{=} \PYG{n}{Button}\PYG{p}{(}\PYG{n}{te
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu} \PYG{o}{=} \PYG{n}{DropDown}\PYG{p}{(}\PYG{p
\PYG{k}{for} \PYG{n}{x} \PYG{o+ow}{in} \PYG{p}{(} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Mustafa
\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{x}\PYG{p}
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}release}\PYG{o}{=}\PYG{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{anadugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYG
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o}{.}\PY
\PYG{k}{return} \PYG{n}{duzen}
\PYG{n}{acilirKutu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Bu programda gördüğünüz gibi, açılır kutuya eklediğimiz her düğmenin on_release eylemine (tıklanıp
bırkalma) secim() işlevini bağladık. Diğer bir deyişle açılır kutudaki düğmelerden herhangi biri seçildiğinde secim() işlevi çağrılacaktır. Bu işlev çağrıldığında açılır kutunun ilgili düğmesi seçilmiş olacak
(acilirkutu.select(nesne.text) ile) ve anadugme nin üzerindeki metin, seçilmiş olan düğmenin üzerindeki metin olacaktır. Programınız çalıştığında Şekil 9.9 deki gibi görünmelidir.
Aynı programı kv dili ile yazacak olursak:
9.2. Açılır Kutu
87
Kivy Mobil Programlama, Sürüm 0.1
Şekil 9.9: Basit Açılır Kutu
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{n+nn}{kivy.uix.dropdown} \PYG{k+kn}{import} \PYG{n}{DropDown}
\PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{n+nn}{kivy.lang} \PYG{k+kn}{import} \PYG{n}{Builder}
\PYG{n}{kv}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}\PYGZsq{}\PYGZsq{}}
\PYG{l+s+s1}{BoxLayout:
}
\PYG{l+s+s1}{
Button:}
\PYG{l+s+s1}{
id: anadugme}
\PYG{l+s+s1}{
text: }\PYG{l+s+s1}{\PYGZdq{}}\PYG{l+s+s1}{Başlat}\PYG{l+s+s1}{\PYGZdq{}}
\PYG{l+s+s1}{
on\PYGZus{}release: app.acilirkutu.open(self)}
\PYG{l+s+s1}{
size\PYGZus{}hint: (None, None)}
\PYG{l+s+s1}{\PYGZsq{}\PYGZsq{}\PYGZsq{}}
\PYG{k}{class} \PYG{n+nc}{acilirKutuKv}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{secim}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)}\PY
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{select}\PYG{p}{(}\PYG{n}{ne
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{anadugme}\P
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{=}\PYG{n}{Builder}\PYG{o}{.}\PYG{n}{load\PY
88
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu} \PYG{o}{=} \PYG{n}{DropDown}\PYG{p}{(}\PYG{p
\PYG{k}{for} \PYG{n}{x} \PYG{o+ow}{in} \PYG{p}{(} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Mustafa
\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{x}\PYG{p}
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}release}\PYG{o}{=}\PYG{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG
\PYG{k}{return} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}
\PYG{n}{acilirKutuKv}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Herhangi bir düğmeye herhangi bir özellik ekleyerek başka verileri saklayabiliriz. Örneğin öğrencilerin okul numaralarını saklamak için şu kodu yazabiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{for} \PYG{n}{x}\PYG{p}{,} \PYG{n}{y} \PYG{o+ow}{in} \PYG{p}{(}\PYG{p}{(}\PYG{l+s+s
\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Fatih}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{,} \P
\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{x}\PYG{p}{,} \PYG
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{okulNo}\PYG{o}{=}\PYG{n}{y}
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}release}\PYG{o}{=}\PYG{n+nb+bp}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\P
Sakladığımız bu veriyi seçim yaptıktan sonra erişebiliriz. “Başlat” düğmesinde saçim yapıldıktan sonra hem isim
hemde okul numarasını görüntülemek istiyorsak:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{anadugme}\PYG{o}{.}\PYG{n}{text}\PYG{o}{=}\PYG{l+s+s2
9.2.1 Seçimin Denetlenmesi
Peki seçilmiş maddeyi nasıl belirleyeceğiz. Diğer bir deyişle tekrar seçim yapılacağı zaman daha önce seçilmiş olan
düğmeyi nasıl göstereceğiz? Liste görünümü (ListView) bunu kendisi yapıyordu, açılır kutuda bunu kendimiz yapmamız gerekecek. Bir seçim yapıldığında, seçilen nesnenin (burada bildiğimiz düğme - Button) arka plan rengini
değiştirebiliriz. Bunu hemen secim() işlevinin altına şu satırı yazarak gerçekleştirebiliriz:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{background\PYGZus{}color}\PYG{o}{=} \PYG{l+m+mi}{1}\PYG{p}
secim() işlevinin altına bu satırı ekledikten sonra programı çalıştırırsanız, bir seçim yapıp tekrar seçim yapmak
istediğinizde önceki düğmenin arka plan renginin kırmızı olduğunu göreceksiniz. İşmiz bitti mi? Bu cevabı iknci ve
üçncü seçimi yaptıktan sonra siz verin. Ne oldu? Her seçilenin arkası kırmızıya dönüşüyor değil mi? Şimdi çözmemiz
gereken başka bir sorun var. Daha önce seçilmiş düğmenin arka plan rengini eski haline getirmek. Düğmelerin ön tanımlı arka plan rengi [1, 1, 1, 1] dir. Bunu yapmak için iki yolumuz var, ya açılır kutudaki tüm düğmelerin arka
plan rengini önce [1, 1, 1, 1] yapmak daha sonra, yeni seçilenin arka plan rengini [1, 0, 0, 1] yapmak.
Ya da benim daha çok sevdiğim ikinci yöntem: açılır kutuya secim özelliği verip, her seçim yapıldığında seçilen nesneyi buraya atamak. Böylelikle daha sonra bir açılır kutudaki seçilmiş nesneye ait bilgilere de ulaşabilirsiniz (aslında
çok basit ikinci yöntemi Kivy geliştiricileri neden eklemezler bilmiyorum). Bu ikinci yöntemi uygulamak için açılır
kutuyu tanımladığımız satırdan sonra (Liste 9.10‘da 19. satıra) aşağıdaki satırı eklemeliyiz:
9.2. Açılır Kutu
89
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n+n
Bu durumda secim() işlevini aşağıdaki gibi değiştirmemiz gerekecek:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{k}{def} \PYG{n+nf}{secim}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p
\PYG{c+c1}{\PYGZsh{} Önceden seçilmiş bir düğme var ise arka plan rengini}
\PYG{c+c1}{\PYGZsh{} ön tanımlı renge dönüştürelim}
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{secim}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{.}\PYG{n}{bac
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{select}\PYG{p}{(}\PYG{n}{nesne}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{anadugme}\PYG{o}{.}\PYG{n}{text}\PYG{o}{=}\PYG{n}{nesne}\PYG
\PYG{c+c1}{\PYGZsh{} secim özelliğine yeni nesneyi ekleyelim ve}
\PYG{c+c1}{\PYGZsh{} arka plan rengini kırmızı yapalım}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{acilirkutu}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n}{nesne}
\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{background\PYGZus{}color}\PYG{o}{=} \PYG{l+m+mi}{1}\PYG{p}{,} \PY
Üçüncü çözümü olan var mı?
9.2.2 İller-İlçeler-Semtler: SqLite Veritabanı
İl-ilçe-semt seçimini İl-İlçe-Mahalle Seçimi kesiminde xml ile yapmıştık ve orada bu kadar büyük veriyi xml ile saklamanın çok mantıklı olmadığını belirtmiştik. Burada aynı uygulamayı liste görünümü yerine açılır kutu ile yapacağız
ve veritabanı olarak xml yerine SqLite kullanacağız.
SqLite oldukça hızlı, küçük (hafif), büyük veriler ile rahatlıkla başedebilen ve yaygın bir veritabanı sistemidir. Üstelik
veri bir dosyada tutulduğundan değişik diller ile yazılmış programlar rahatlıkla erişebilir ve ağ üzerinden dağıtılabilir.
Python ile SqLite bağlantısı sqlite3 modülü ile gerçekleştirilir. Önce basitçe kullanımını hatırlayalım. Bu amaçla
bir veritabanı oluşturalım ve bağlantısını gerçekleştirelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k+kn}{import} \PYG{n+nn}{sqlite3}
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{sqlbaglantisi} \PYG{o}{=} \PYG{n}{sqlite3}\PYG{o}{.}\
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{isaretci} \PYG{o}{=} \PYG{n}{sqlbaglantisi}\PYG{o}{.}
ogrenciler tablosunu oluşturalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{execute}\PYG{p}
tabloya birkaç veri ekleyelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k}{for} \PYG{n}{x}\PYG{p}{,} \PYG{n}{y} \PYG{
\PYG{g+gp}{... }
\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{execute}\PYG{p}{(}\PYG{l+s+s1}{\PYGZsq{}}\PYG{
\PYG{g+gp}{...}
90
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Eklediğimiz verinin diske (dosyay) yazılmasını sağlayalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{sqlbaglantisi}\PYG{o}{.}\PYG{n}{commit}\PY
Şimdi de eklediğimiz öğrencileri tekrar alalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{execute}\PYG{p}
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{ogrenciler}\PYG{o}{.}\PYG{n}{fetchall}\PYG{p}{(}\PYG{
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k}{for} \PYG{n}{ogr} \PYG{o+ow}{in} \PYG{n}{ogrenciler}\
\PYG{g+gp}{... }
\PYG{k}{print} \PYG{n}{ogr}
\PYG{g+gp}{...}
\PYG{g+go}{(1, u\PYGZsq{}Mustafa\PYGZsq{}, 9876)}
\PYG{g+go}{(2, u\PYGZsq{}Dilek\PYGZsq{}, 77192)}
\PYG{g+go}{(3, u\PYGZsq{}Fatih\PYGZsq{}, 98278)}
\PYG{g+go}{(4, u\PYGZsq{}Melike\PYGZsq{}, 56765)}
Veritabanına yapılmış bağlantıyı koparalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{sqlbaglantisi}\PYG{o}{.}\PYG{n}{close}\PYG
Daha önce size verdiğim Il-ilce-Semt-Mahalle-PostaKodu.xml dosyasındaki tüm tablo ve verileri SqLite
biçimine dönüştürdüm. SqLite dosyasını şu adresten alabilirziniz:
iller.db: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/5/iller.db
Dosyayı indirdiğiniz patikanın tam adını veritabanı dosyasının patikasını yazarak deneyelim:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k+kn}{import} \PYG{n+nn}{sqlite3}
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{sqlbaglantisi} \PYG{o}{=} \PYG{n}{sqlite3}\PYG{o}{.}\
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{isaretci} \PYG{o}{=} \PYG{n}{sqlbaglantisi}\PYG{o}{.}
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{execute}\PYG{p}{(}\PYG{l+s
\PYG{g+go}{\PYGZlt{}sqlite3.Cursor object at 7f3c8ebc7
PYGZgt{}}
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{n}{iller}\PYG{o}{=}\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{fe
\PYG{g+gp}{\PYGZgt{}\PYGZgt{}\PYGZgt{} }\PYG{k}{for} \PYG{n}{il} \PYG{o+ow}{in} \PYG{n}{iller}\PYG{p}
\PYG{g+gp}{... }
\PYG{k}{print} \PYG{n}{il}\PYG{p}{[}\PYG{l+m+mi}{}\PYG{p}{]}\PYG{p}{,} \PYG{n}{il
\PYG{g+gp}{...}
\PYG{g+go}{1 Adana}
\PYG{g+go}{2 Adıyaman}
\PYG{g+go}{3 Afyonkarahisar}
\PYG{g+go}{4 Ağrı}
\PYG{g+go}{5 Amasya}
\PYG{g+go}{.}
\PYG{g+go}{.}
\PYG{g+go}{.}
Veritabanımız hazır olduğuna göre programımızı yazabiliriz (Liste 9.11).
9.2. Açılır Kutu
91
Kivy Mobil Programlama, Sürüm 0.1
Liste 9.11: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{n+nn}{kivy.uix.dropdown} \PYG{k+kn}{import} \PYG{n}{DropDown}
\PYG{n+nn}{kivy.uix.button} \PYG{k+kn}{import} \PYG{n}{Button}
\PYG{k+kn}{import} \PYG{n+nn}{sqlite3}
\PYG{n}{sqlbaglantisi} \PYG{o}{=} \PYG{n}{sqlite3}\PYG{o}{.}\PYG{n}{connect}\PYG{p}{(}\PYG{l+s+s1}{\P
\PYG{n}{isaretci} \PYG{o}{=} \PYG{n}{sqlbaglantisi}\PYG{o}{.}\PYG{n}{cursor}\PYG{p}{(}\PYG{p}{)}
\PYG{k}{class} \PYG{n+nc}{illerIlcelerAcilirKutu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{secimIl}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)}\
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{iller}\PYG{o}{.}\PYG{n}{secim}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{iller}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{.}\PYG{n}{back
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{iller}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n}{nesne}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{iller}\PYG{o}{.}\PYG{n}{select}\PYG{p}{(}\PYG{n}{nesne}\
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{iller}\PYG{
\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{background\PYGZus{}color}\PYG{o}{=} \PYG{l+m+mi}{1}\PYG{p}{,}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler}\PYG{o}{.}\PYG{n}{clear\PYGZus{}widgets}\PYG{p}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{clear\PYGZus{}widgets}\PYG{p}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{ilceler}\PY
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{semtler}\PY
\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{execute}\PYG{p}{(}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{SELE
\PYG{k}{for} \PYG{n}{ilce} \PYG{o+ow}{in} \PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{fetchall}\PYG{p}
\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{ilce}\PYG
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{ilce\PYGZus{}id}\PYG{o}{=}\PYG{n}{ilce}\PYG{p}{[}\PYG{l+m
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}release}\PYG{o}{=}\PYG{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}
\PYG{k}{def} \PYG{n+nf}{secimIlce}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler}\PYG{o}{.}\PYG{n}{secim}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{.}\PYG{n}{ba
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n}{nesne}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler}\PYG{o}{.}\PYG{n}{select}\PYG{p}{(}\PYG{n}{nesne
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{ilceler}\PY
\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{background\PYGZus{}color}\PYG{o}{=} \PYG{l+m+mi}{1}\PYG{p}{,}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{clear\PYGZus{}widgets}\PYG{p}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{semtler}\PY
\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{execute}\PYG{p}{(}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{SELE
\PYG{k}{for} \PYG{n}{semt} \PYG{o+ow}{in} \PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{fetchall}\PYG{p}
\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{semt}\PYG
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{semt\PYGZus{}id}\PYG{o}{=}\PYG{n}{semt}\PYG{p}{[}\PYG{l+m
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}release}\PYG{o}{=}\PYG{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}
92
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
\PYG{k}{def} \PYG{n+nf}{secimSemt}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{nesne}\PYG{p}{)
\PYG{k}{if} \PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{secim}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{.}\PYG{n}{ba
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n}{nesne}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{select}\PYG{p}{(}\PYG{n}{nesne
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{semtler}\PY
\PYG{n}{nesne}\PYG{o}{.}\PYG{n}{background\PYGZus{}color}\PYG{o}{=} \PYG{l+m+mi}{1}\PYG{p}{,}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{iller} \PYG{o}{=} \PYG{n}{DropDown}\PYG{p}{(}\PYG{p}{)}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{iller}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n+nb+bp}{No
\PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{execute}\PYG{p}{(}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{SELE
\PYG{k}{for} \PYG{n}{il} \PYG{o+ow}{in} \PYG{n}{isaretci}\PYG{o}{.}\PYG{n}{fetchall}\PYG{p}{(
\PYG{n}{dugme}\PYG{o}{=}\PYG{n}{Button}\PYG{p}{(}\PYG{n}{text}\PYG{o}{=}\PYG{n}{il}\PYG{p
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{il\PYGZus{}id}\PYG{o}{=}\PYG{n}{il}\PYG{p}{[}\PYG{l+m+mi}
\PYG{n}{dugme}\PYG{o}{.}\PYG{n}{bind}\PYG{p}{(}\PYG{n}{on\PYGZus{}release}\PYG{o}{=}\PYG{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{iller}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler} \PYG{o}{=} \PYG{n}{DropDown}\PYG{p}{(}\PYG{p}{)
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{ilceler}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n+nb+bp}{
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler} \PYG{o}{=} \PYG{n}{DropDown}\PYG{p}{(}\PYG{p}{)
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{semtler}\PYG{o}{.}\PYG{n}{secim}\PYG{o}{=}\PYG{n+nb+bp}{
\PYG{n}{illerIlcelerAcilirKutu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
ve kv dosyası:
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYGZlt{}illerIlcelerAcilirKutu\PYGZgt{}:
BoxLayout:
Button:
id: iller
text: \PYGZdq{}İl Seçiniz\PYGZdq{}
on\PYGZus{}release: app.iller.open(self)
size\PYGZus{}hint\PYGZus{}y: None
height: 3
Button:
id: ilceler
text: \PYGZdq{}İlçe Seçiniz\PYGZdq{}
on\PYGZus{}release: app.ilceler.open(self)
size\PYGZus{}hint\PYGZus{}y: None
height: 3
Button:
id: semtler
text: \PYGZdq{}Semt Seçiniz\PYGZdq{}
on\PYGZus{}release: app.semtler.open(self)
size\PYGZus{}hint\PYGZus{}y: None
Not: Derleme yaparken (Paket Derleme kısmında anlatılan) buildozer in paketin içine sqlite modülünü koyması için
requirements seçeneğinin şu şekilde yapılandırılması gerekir:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{requirements} \PYG{o}{=} \PYG{n}{kivy}\PYG{p}{,}\PYG{n}{sqlite3}
9.2. Açılır Kutu
93
Kivy Mobil Programlama, Sürüm 0.1
Bunun dışında iller.db dosyasının içerilebilmesi için source.include_exts seçeneğinin sonuna db eklenemsi gerekir (tüm db uzantılı dosyalar içerilecektir):
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{source}\PYG{o}{.}\PYG{n}{include\PYGZus{}exts} \PYG{o}{=} \PYG{n}{py}\PYG{p}{,}\PY
9.3 Eylem Çubuğu
Mobil programlamada eylem çubuğu (ActionBar), masaüstü programlardaki menu çubuğu ve/veya araç çubuğuna
benzetelebilir (yapısal olarak farklı olasa da). Eylem çubuğunu genellikle pencerinin üstüne koyarız ve programın
yapılandırılması veya diğer eylemler için birkaç düğme ve/veya düğme grubu koyarız. Böylelikle programın kullanılmasını sağlarız.
Bir eylem çubğu en azından bir eylem görünümü (ActionView) ve bunun içinde önceki eylem (ActionPrevious) nesnesinden oluşmalıdır. Diğer bir deyişle bir eylem çubuğu oluşturmak için en azından ActionBar, ActionView
ve ActionPrevious nesnelerini kullanmamız gerekecek. Bu bilgilerden sonra hemen bir eylem çubuğu oluşturan
program yazalım (Liste 9.12)
Liste 9.12: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.boxlayout} \PYG{k+kn}{import} \PYG{n}{BoxLayout}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.uix.label} \PYG{k+kn}{import} \PYG{n}{Label}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{k+kn}{from}
\PYG{n+nn}{kivy.uix.actionbar}
\PYG{n+nn}{kivy.uix.actionbar}
\PYG{n+nn}{kivy.uix.actionbar}
\PYG{n+nn}{kivy.uix.actionbar}
\PYG{k+kn}{import} \PYG{n}{ActionBar}
\PYG{k+kn}{import} \PYG{n}{ActionView}
\PYG{k+kn}{import} \PYG{n}{ActionButton}
\PYG{k+kn}{import} \PYG{n}{ActionPrevious}
\PYG{k}{class} \PYG{n+nc}{eylemCubugu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{n}{eylemcubugu}\PYG{o}{=} \PYG{n}{ActionBar}\PYG{p}{(}\PYG{n}{pos\PYGZus{}hint}\PYG{o}{=
\PYG{n}{eylemgorunumu}\PYG{o}{=}\PYG{n}{ActionView}\PYG{p}{(}\PYG{p}{)}
\PYG{n}{eylemcubugu}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{eylemgorunumu}\PYG
\PYG{n}{oncekieylem}\PYG{o}{=}\PYG{n}{ActionPrevious}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PYG{l
\PYG{n}{eylemgorunumu}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{oncekieylem}\PYG
\PYG{n}{duzen} \PYG{o}{=} \PYG{n}{BoxLayout}\PYG{p}{(}\PYG{n}{orientation}\PYG{o}{=}\PYG{l+s+
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n}{eylemcubugu}\PYG{p}{)}
\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{etiket}\PYG{o}{=}\PYG{n}{Label}\PYG{p}{(}\PYG{n}{text}\P
\PYG{n}{duzen}\PYG{o}{.}\PYG{n}{add\PYGZus{}widget}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{o}{.}\PY
\PYG{k}{return} \PYG{n}{duzen}
94
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
\PYG{n}{eylemCubugu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
Burada gördüğünüz gibi öncelikle bir eylem çubuğu (ActionBar) oluşturuyoruz. Bu çubuğun, bulunduğu alandaki konumunu üst taraf yapmak için pos_hint parametresine {’top’:1} değerini veriyoruz. Önceki eylem
(ActionPrevious) nesnesinin title parametresine genellikle programın adını veriririz (unutmayın mobil cihazlarda pencere başlığı olmayacaktır). Yatay yerleşimli kutu pencere düzeninin ilk elemanı eylem çubuğu, ikinci
elemanı ise bir etiket oldu. İkinci eleman yerine genellikle bir başka pencere düzeni koymayı yeğleriz ki, programımızın ana penceresinde görünmesini istediğimiz nesneleri yerleştirelim. Programımızı çalıştırdığımızda elde edeceğimiz
pencere Şekil 9.10 ‘da verilmiştir.
Şekil 9.10: Eylem Çubuğu
Burada başlığın solunda bir simgenin olduğunu görüyorsunuz. Eğer önceki eylem (ActionPrevious) nesnesinin
app_icon parametresine bir simge vermez isek ön tanımlı olarak kivy simgesi görünür. Bu simgenin nereden geldiğini
daha donra açıklayacağız. İsterseniz şimdi bu simgeyi değiştirelim. Bunun için main.py programını kaydettiğiniz
yere şu resmi indirin:
document-edit.png: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/6/documentedit.png
Daha sonra 21. satırdaki ActionPrevious
document-edit.png verin:
nesnesinin
aşağıdaki
gibi
app_icon
parametresine
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{oncekieylem}\PYG{o}{=}\PYG{n}{ActionPrevious}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PY
9.3.1 atlas
Yukarıdaki değişikliği yapıp programı çalıştırırsanız soldaki simgenin değiştiğini göreceksiniz. Peki bu ön tanımlı
simge nereden geliyor? Cevabını vereyim atlas dan. Gerçekten atlas nesnesinden geliyor. atlas nesnesi programda
9.3. Eylem Çubuğu
95
Kivy Mobil Programlama, Sürüm 0.1
kullanacağınız simgeleri bir tek resim haline getirip, bunu indeksleyip daha sonra bu simgeleri kullanmamızı sağlar.
Elbetteki atlas nesnesinin ön tanımlı bir simge seti var. Kivy’nin kurulu olduğu dizindeki data/images klasöründe (benim Linux’umda tam patika /usr/lib/python2.7/dist-packages/kivy/data/images,
Windows’umda tam patika C:\Python27\Lib\site-packages\kivy\data\images) bulunan
defaulttheme-0.png dosyası kullanılan ön tanımlı simgelerin birleşmesinden oluşan dosya, bu dosyanın ineksi
ise defaulttheme.atlas dosyasında bulunmaktadır. defaulttheme.atlas dosyası bildiğimiz Python sözlüğüdür. Bu sözlüğün içinde çeşitli simge gruplarından oluşan indeksler bulunur. Örneğin defaulttheme-0.png
anahtarının değeri yine bir szölük ve burada simgelerin konumları bulunmaktadır. Bir örnek verecek olursak
audio-volume-medium simgesi [52, 171, 48, 48] konumunda bulunmaktadır. Bir programı apk paketi
haline getirdiğinizde atlas’ın ön tanımlı dosyasıda içerisinde bulunduğundan buradaki simgeleri istediğiniz yerde
kullanabilirsiniz. Şimdi document-edit.png yerine atlas’ın içerisinde bulunan close simgesini koyalım, bunun
için Liste 9.12 deki 21. satırı aşağıdaki gibi değiştirin:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{oncekieylem}\PYG{o}{=}\PYG{n}{ActionPrevious}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PY
atlas’ın simgelerinin kullanımını şöyle açıklayabiliriz: /atlas/icin/patika/atlas_dosyasi/simge_adi Burada şuna dikkat
etmelisiniz simge_adi sadece ismi içerir, dosya uzantısını içermez. Bu ön tanımlı simgeleri programınıza herhangi
bir ekleme yapmadan kullanabilir, öylece paketleyebilirsiniz.
Şimdi kendi atlas’ımızı oluşturalım. Bunun için şu dosyayı indirin ve programınızın (mevcut main.py dosyasının
olduğu) patikaya açın:
simgeler.png: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/6/simgeler.zip
Şimdi komut satırından (cmd) aşağıdaki komutu çalıştırın 1 2 :
=
{}=
{}@default
=0=1=2=0=1=2\PYG{g+gp}{\PYGZdl{}} python \PYGZhy{}m kivy.atlas atlasim 256x256 simgeler/*.png
Bu komut bulunduğunuz dizinde iki adet dosya oluşturacaktır. Birincisi atlas indeksi (atlasim.atlas), diğeri simgelerin birleştirildiği 256x256 boyutlarında bir PNG dosyası olan atlas resimidir (atlasim-0.png). Çalıştırdığımız
komutun ilk kısmını zaten biliyorsunuz, atlas’ın nasıl çalıştığını anlatalım:
• İlk aldığı argüman isimdir. Burada atlasim ismini verdik. Daha sonra kullanırken bu ismi yazacağız.
• İkinci argüman oluşturulacak atlas resminin boyutlarıdır. Eğer resimleriniz büyükse daha büyük bir boyut kullanabilirsiniz. enxboy şeklinde yazılır
• Üçüncü argüman ise atlas’a eklenecek simgelerdir. Burada bulunduğumuz dizindeki simgeler dizini altındaki
tüm PNG dosyalarını eklemesini istedik.
Şimdi oluşturduğumuz atlası Liste 9.12 deki 21. satırı aşağıdaki gibi değiştirerek kullanalım:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{oncekieylem}\PYG{o}{=}\PYG{n}{ActionPrevious}\PYG{p}{(}\PYG{n}{title}\PYG{o}{=}\PY
1
Sismteminizde PIL kurulu değil ise komut satırından şu şekilde kurabilirsiniz: python -m pip install Pillow
Windows kullanıcıları cmd yi yönetici (Administrator) yetkileri ile çalışırmaları gerekebilir. Eğer Windows kullanıcıları patikaya Python’u eklemedilerse tam patikayı yazmalıdırlar. Örneğin: C:\Python27\python.exe -m kivy.atlas atlasim 256x256
simgeler/*.png
2
96
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Unutmayın atlasim-0.png ve atlasim.atlas doslayalrı Liste 9.12 programının kayıtlı olduğu dizinde olmalıdır. Burada document-edit.png simgesini kullanmak için sadece dosya adını (document-edit) yazdığımızıda aklınızdan çıkarmayın.
Oluşturduğumuz atlasim.atlas ve atlasim-0.png dosyalarını şuradan indirebilirsiniz:
atlasim.atlas: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/6/atlasim.atlas
atlasim-0.png: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/6/atlasim0.png
Not: Derleme yaparken (Paket Derleme kısmında anlatılan), buildozer.spec dosyasında herhangi bir değişiklik
yapmanıza gerek yok. Çünkü, buildozer.spec dosyasındaki source.include_exts yapılandırma seçeneği
ön tanımlı olarak atlas ve png doslayarını paketin içerisine koyacak şekilde yapılandırılmıştır.
9.3.2 Eylemler
Aslında eylem öncesine, tıklandığında eylemlerin gerçekleşeceği birtakım nesnelerin yerleştirilmesi gerekiyor. Bunu
bildiğimiz düğmeler (Button) kullanarak yapabilirsiniz. Ancak bunun yerine eylem düğmesi (ActionButton) kullanmanızı tavsiye ederim. Eylem düğmeleri, normal bir düğme gibi çalışır. Buna ilaveten bir de simge yerleştirebilirsiniz.
Masaüstü programların araç çubuğunda bulunan düğmelere benzetebilirsiniz. Şimdi bunlardan birini ekleyelim. Bunun
için yapmanız gereken Liste 9.12 de 23. satırdan sonra şunları yazmak:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n}{ac\PYGZus{}eylem\PYGZus{}dugmesi}\PYG{o}{=}\PYG{n}{ActionButton}\PYG{p}{(}\PYG{n}{
\PY
Bu iki satırı eklediğinizde, eylem çubuğunun sağında üzerinde=16pt=16pt@default=16pt=16pt@default simgesinin
bulunduğu bir düğme eklenecektir. Elbetteki düğmemizin şimdilik bir görevi yok.
Programımızı kv dili ile yazıp rahata erelim. Python programı şu şekilde olmalıdır (Liste 9.13):
Liste 9.13: main.py
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
=0=1=2=0=1=2 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\PYGZhy{}8 \PYGZhy{}*\PYGZhy{}}
\PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App}
\PYG{k}{class} \PYG{n+nc}{eylemCubugu}\PYG{p}{(}\PYG{n}{App}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{def} \PYG{n+nf}{build}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{)}\PYG{p}{:}
\PYG{k}{pass}
\PYG{n}{eylemCubugu}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)}
ve kv dosyası (Liste 9.14):
Liste 9.14: eylemcubugu.kv
=
{}=
{}@default=left=left@default=1=1@default=1=1@default
9.3. Eylem Çubuğu
97
Kivy Mobil Programlama, Sürüm 0.1
=0=1=2=0=1=2 \PYGZlt{}eylemCubugu\PYGZgt{}:
BoxLayout:
orientation: \PYGZsq{}vertical\PYGZsq{}
pos\PYGZus{}hint: \PYGZob{}\PYGZsq{}top\PYGZsq{}:1\PYGZcb{}
ActionBar:
ActionView:
ActionPrevious:
title: \PYGZsq{}Metin Düzenleyici\PYGZsq{}
with\PYGZus{}previous: False
app\PYGZus{}icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}edit\PYGZsq{}
ActionButton:
text: \PYGZsq{}Aç\PYGZsq{}
id: ac\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}open\PYGZsq{}
ActionButton:
text: \PYGZsq{}Kaydet\PYGZsq{}
id: kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZsq{}
ActionButton:
text: \PYGZsq{}Farklı Kaydet\PYGZsq{}
id: farklı\PYGZus{}kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZhy{}as\PYGZsq{}
ActionButton:
text: \PYGZsq{}Yeni\PYGZsq{}
id: yeni\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}new\PYGZsq{}
ActionButton:
text: \PYGZsq{}Çık\PYGZsq{}
id: yeni\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/application\PYGZhy{}exit\PYGZsq{}
Label:
text: \PYGZsq{}Ana Alan\PYGZsq{}
Hiçbir iş yapmayan programımızı çalıştırdığımızda Şekil 9.11 daki görüntüyü elde edeceğiz.
Sanırım neden bu düğmeleri seçtiğimizi anladınız. Aslında eylem düğmelerini, normal düğmeleri (Button) kullandığınız yerlerin çoğunda kullanma şansınız var. Burada eylem öncesi nesnesinin (ActionPrevious) simgesinin solunda “<”
var idi. Bunu kaldırmak için bu nesnenin with_previous özelliğine False değerini verdik.
9.3.3 Metin Düzenleyici Yeniden
Şimdi hazırladığımız eylem çubuğu ile Metin Düzenleyici bölümünde hazırladığımız metin düzenleyiciyi
birleştirelim. Öncelikle kv dosyasını düzenleyelim. Bunun için metinduzenleyici.kv dosyasındaki
<metinDuzenleyici>: formunda (dosyanın başındaki form) aşağıdaki satırları silin:
=
{}=
{}@default
=0=1=2=0=1=2BoxLayout:
text: \PYGZdq{}Aç\PYGZdq{}
on\PYGZus{}press: app.dosyaAcIsleviDialog()
Button:
text: \PYGZdq{}Kaydet\PYGZdq{}
on\PYGZus{}press: app.dosyaKaydetIslevi()
Button:
98
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Şekil 9.11: Eylem Çubuğu ve Eylem Düğmeleri
9.3. Eylem Çubuğu
99
Kivy Mobil Programlama, Sürüm 0.1
text: \PYGZdq{}Farklı Kaydet\PYGZdq{}
on\PYGZus{}press: app.farkliKaydetDialog()
Button:
text: \PYGZdq{}Yeni\PYGZdq{}
on\PYGZus{}press: app.yeniDosyaAcIslevi()
Button:
id: cik\PYGZus{}dugmesi
size\PYGZus{}hint\PYGZus{}x: .15
background\PYGZus{}color: ( 1, 1)
on\PYGZus{}press: app.cik()
ve bunların yerine TextInput: satırından önce (exit_on_escape: False dan sonra) aşağıdakileri yazın:
=
{}=
{}@default
=0=1=2=0=1=2ActionBar:
pos\PYGZus{}hint: \PYGZob{}\PYGZsq{}top\PYGZsq{}:1\PYGZcb{}
ActionView:
ActionPrevious:
title: \PYGZsq{}Metin Düzenleyici\PYGZsq{}
id: eylem\PYGZus{}oncesi
with\PYGZus{}previous: False
app\PYGZus{}icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}edit\PYGZsq{}
ActionButton:
text: \PYGZsq{}Aç\PYGZsq{}
id: ac\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}open\PYGZsq{}
on\PYGZus{}press: app.dosyaAcIsleviDialog()
ActionButton:
text: \PYGZsq{}Kaydet\PYGZsq{}
id: kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZsq{}
on\PYGZus{}press: app.dosyaKaydetIslevi()
ActionButton:
text: \PYGZsq{}Farklı Kaydet\PYGZsq{}
id: farklı\PYGZus{}kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZhy{}as\PYGZsq{}
on\PYGZus{}press: app.farkliKaydetDialog()
ActionButton:
text: \PYGZsq{}Yeni\PYGZsq{}
id: yeni\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}new\PYGZsq{}
on\PYGZus{}press: app.yeniDosyaAcIslevi()
ActionButton:
text: \PYGZsq{}Çık\PYGZsq{}
id: cik\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/application\PYGZhy{}exit\PYGZsq{}
on\PYGZus{}press: app.cik()
ve son olarak main.py dosyasında çıkış düğmesinin rengini değiştirdiğimiz yerlerde, renk değişikliği yerine simge
değişikliği yapabilmek için şu satırların yerine:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{cik\PYGZ
şu satırı yazın (toplam 4 satır değişikliğ):
100
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{cik\PYGZ
şu satır yerine:
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{cik\PYGZ
şu satırı yazın (1 satır değişikliği):
=
{}=
{}@default
=0=1=2=0=1=2\PYG{n+nb+bp}{self}\PYG{o}{.}\PYG{n}{root}\PYG{o}{.}\PYG{n}{ids}\PYG{o}{.}\PYG{n}{cik\PYGZ
yapacağınız değişikliklerin hepsi bu kadar. Elbetteki atlasim.atlas ve atlasim-0.png dosyalarını metin düzenleyici programımızın olduğu dizine kopyalamayı unutmayacağız. Şimdi metin düzenleyici programımız daha çekici oldu. Programımızı çalıştırdığımızda Şekil 9.12 daki görüntüyü elde edeceğiz.
Şekil 9.12: Eylem Çubuklu Metin düzenleyici
9.3. Eylem Çubuğu
101
Kivy Mobil Programlama, Sürüm 0.1
Programın son halini şuradan alabilirsiniz:
atlasim.atlas: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/8/atlasim.atlas
atlasim-0.png: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/8/atlasim0.png
main.py: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/8/main.py
metinduzenleyici.kv: https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/8/metinduzenley
Soru: Şekil 9.12 deki ekran görüntüsününde eylem öncesi nesnesinin başlığı, açılan (ya da kaydedilen) dosyanın dosya
adını göstermektedir. Bunu siz de yapabilirmisiniz? İpucu: self.root.ids.eylem_oncesi.title metnini
dosya adı yapmalısınız.
Metin düzenleyicinin son halini derledim ve denemeniz için aşağıdaki köprüye koydum:
https://raw.githubusercontent.com/mbaser/kivy-tr/master/docs/programlar/listeEylem/programlar/8/kivymetinduzenleyici0.3.apk
Programın Android öykünücüdeki çalışan hali ise şöyle:
Şekil 9.13: Android öykünücüde çalışan Metin Düzenleyici
102
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
9.3.4 Eylem Düğmelerini Ayırma ve Gruplama
Eylem düğmeleri arasına ayıraç koyarak, tıpkı masaüstü programlarda bulunan araç çubuklarında olduğu gibi, birbirinden ayırabilirsiniz. Ayıraç koymak istediğiniz düğmelerin arasına (kv dosyasında) ActionSeparator nesnesi koymalısınız. Örneğin “Kaydet” ve “Farklı Kaydet” arasına ayıraç koymak için metinduzenleyici.kv dosyasının
ActionBar kısımını aşağıdaki gibi düzenleyebilirsiniz:
=
{}=
{}@default
=0=1=2=0=1=2ActionBar:
ActionView:
ActionPrevious:
title: \PYGZsq{}Metin Düzenleyici\PYGZsq{}
id: eylem\PYGZus{}oncesi
with\PYGZus{}previous: False
app\PYGZus{}icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}edit\PYGZsq{}
ActionButton:
text: \PYGZsq{}Aç\PYGZsq{}
id: ac\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}open\PYGZsq{}
on\PYGZus{}press: app.dosyaAcIsleviDialog()
ActionSeparator:
ActionButton:
text: \PYGZsq{}Kaydet\PYGZsq{}
id: kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZsq{}
on\PYGZus{}press: app.dosyaKaydetIslevi()
ActionButton:
text: \PYGZsq{}Farklı Kaydet\PYGZsq{}
id: farklı\PYGZus{}kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZhy{}as\PYGZsq{}
on\PYGZus{}press: app.farkliKaydetDialog()
ActionSeparator:
ActionButton:
text: \PYGZsq{}Yeni\PYGZsq{}
id: yeni\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}new\PYGZsq{}
on\PYGZus{}press: app.yeniDosyaAcIslevi()
ActionButton:
text: \PYGZsq{}Çık\PYGZsq{}
id: cik\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/application\PYGZhy{}exit\PYGZsq{}
on\PYGZus{}press: app.cik()
Eylem düğmelerini gruplamak için ActionGroup nesnesini kullanabilirsiniz. Bu nesnenin mode parametresi gruplamanın nasıl yapılacağını belirtir. Ön tanımlı değeri normal dir ve ekranda yer olmadığı zaman gruplama yapar. Yeteri
kadar yer var ise gruplamadan gösterir. Değerini spinner yaparsanız her zaman gruplanır ve simgeler yerine metin
gösterilir. Elebetteki text parametresine grup metnini belirtmeliyiz. Aşağıda metinduzenleyici.kv dosyasının
ActionBar kısımında nasıl kullanılacağı gösterilmiştir:
=
{}=
{}@default
=0=1=2=0=1=2ActionBar:
pos\PYGZus{}hint: \PYGZob{}\PYGZsq{}top\PYGZsq{}:1\PYGZcb{}
ActionView:
ActionPrevious:
title: \PYGZsq{}Metin Düzenleyici\PYGZsq{}
9.3. Eylem Çubuğu
103
Kivy Mobil Programlama, Sürüm 0.1
id: eylem\PYGZus{}oncesi
with\PYGZus{}previous: False
app\PYGZus{}icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}edit\PYGZsq{}
ActionButton:
text: \PYGZsq{}Aç\PYGZsq{}
id: ac\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}open\PYGZsq{}
on\PYGZus{}press: app.dosyaAcIsleviDialog()
ActionGroup:
text: \PYGZsq{}Kaydetme\PYGZsq{}
mode: \PYGZsq{}normal\PYGZsq{}
ActionButton:
text: \PYGZsq{}Kaydet\PYGZsq{}
id: kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZsq{}
on\PYGZus{}press: app.dosyaKaydetIslevi()
ActionButton:
text: \PYGZsq{}Farklı Kaydet\PYGZsq{}
id: farklı\PYGZus{}kaydet\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}save\PYGZhy{}as\PYGZsq{}
on\PYGZus{}press: app.farkliKaydetDialog()
ActionButton:
text: \PYGZsq{}Yeni\PYGZsq{}
id: yeni\PYGZus{}eylem\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/document\PYGZhy{}new\PYGZsq{}
on\PYGZus{}press: app.yeniDosyaAcIslevi()
ActionButton:
text: \PYGZsq{}Çık\PYGZsq{}
id: cik\PYGZus{}dugmesi
icon: \PYGZsq{}atlas://atlasim/application\PYGZhy{}exit\PYGZsq{}
on\PYGZus{}press: app.cik()
Şekil 9.14 de üsstteki resimde pencere yeteri kadar genişken eylem düğmelerinin gruplanmamış hali, alttaki resimde
ise pencere daraltıldığında gruplanmış hali görünüyor. Gruplanmış eylem düğmeleri eylem çubuğunun en sağında yer
alır.
Dipnotlar
104
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
Kivy Mobil Programlama, Sürüm 0.1
Şekil 9.14: Üstte gruplanmamış, altta gruplanmış eylem düğmeleri
9.3. Eylem Çubuğu
105
Kivy Mobil Programlama, Sürüm 0.1
106
Bölüm 9. Liste Görünümü ve Eylem Çubuğu
BÖLÜM 10
Dizinler ve Tablolar
• genindex
• search
107
Kivy Mobil Programlama, Sürüm 0.1
108
Bölüm 10. Dizinler ve Tablolar
Dizin
Symbols
önceki eylem, 94
İşaret Dili, 23
A
açılır kutu, 86
ActionBar, 94
ActionButton, 97
ActionGroup, 103
ActionPrevious, 94
ActionSeparator, 103
ActionView, 94
allow_empty_selection, 77
allow_stretch, 66
Ana Pencere, 7
ana sınıf, 7
app_icon, 95
arg_converter, 75
argüman çevirici, 75
arka plan rengi, 44
atlıkarınca, 59
atlas, 95
auto_dismiss, 26
ayıraç, 103
B
background_color, 44
Box Layout, 16
BoxLayout, 10
build(), 7
Buildozer, 47
C
carousel, 59
clear_widgets, 63
Clock, 67
cls, 73
Config, 44
D
Düğme, 9
data, 73
deselected_color, 76
direction, 60
dismiss, 26
DropDown, 86
E
en-boy oranı, 66
etiket, 7
etkin, 67
event, 21
exit_on_escape, 44
eylem çubuğu, 94
eylem düğmesi, 97
eylem görünümü, 94
F
FileChooserListView, 34
filters, 34
font_size, 68
G
genişletmek, 66
Grafik Parçacığı, 8
Grid Layout, 17
GridLayout, 10
gruplamak, 103
I
icon, 8
Image, 61
item_strings, 71
Izgara Pencere Düzeni, 9, 17
K
keep_ratio, 66
Kivy Dili, 15
kronometre, 68
Kutu Pencere Düzeni, 10, 16
kv lang, 15
109
Kivy Mobil Programlama, Sürüm 0.1
L
U
Label, 7
ListAdapter, 75
ListItemButton, 75
ListView, 71
load_next, 68
load_previous‘, 68
loop, 68
unschedule, 67
M
zamanlayıcı, 66
W
Widget, 9
with_previous, 98
Z
markup, 23
Metin Kutusu, 9
mode, 103
multiline, 32
multiselect, 37, 64
O
olay, 21
on_press, 21
on_release, 86
on_selection, 34
on_selection_change, 79
on_touch_down, 26
P
Parçacık Boyutları, 18
pasifleştirmek, 66
password, 20
popup, 25
Popup Pencere, 25
pos_hint, 95
R
renk, 44
resim, 61
RGB, 44
S
schedule_interval, 67
selected_color, 76
selection, 79
selection_mode, 79
SimpleListAdapter, 72
size, 27
size_hint, 18, 27
source, 61
SqLite, 90
stop(), 46
T
TextInput, 9
timer, 66
title, 7
110
Dizin

Benzer belgeler

phpMyAdmin Documentation

phpMyAdmin Documentation korunduğundan haberiniz olsun ve bir şekilde resmi phpMyAdmin belgelerindekinden farklı olabilir. Özellikle yaptığı: • Web sunucusu yapılandırması (Apache ve lighttpd için çalışır). • dbconfig-...

Detaylı