Kivy Mobil Programlama



Benzer belgeler
Kivy Mobil Programlama

12 TBT / WEB TASARIM ve PROGRAMLAMA ( Not 3 )

LABORATUVAR ÇALIŞMASI 1 - Python a Giriş

HESAP MAKİNASI YAPIMI

Android Ders Notları

BOOTLOADER MANUAL DOCUMENT


3. BELGE DENETİMİ. Bu bölümde belge denetimi için gerekli olan yazım, dil bilgisi ve dil ayarlarını öğreneceğiz.

Microsoft Excel. Çalışma Alanı. Hızlı Erişim Çubuğu Sekmeler Başlık Formül Çubuğu. Ad Kutusu. Sütunlar. Satırlar. Hücre. Kaydırma Çubukları

Bolum 9. Konu Başlıkları

Q-Biz İş Zekası 5.1. Versiyon Yenilikleri

Proje 1. Arayüz Tasarımı

ÖĞRENME FAALİYETİ 1 ÖĞRENME FAALİYETİ 1 1. FORMLAR

<html> <head> <title>sayfa Başlığı</title> </head> <body> Bu benim ilk sayfam <b>bu metin koyu</b> </body> </html>

7. BELGEYE RESİM EKLEME, YAZIM ve ÇİZİM ÖZELLİKLERİ

Blogcu Kullanma Kılavuzu

WebInstaller. 1. Kurulum Đçin Gereksinimler

PERKON PDKS Kurulum ve hızlı başlangıç rehberi


TSOFT FACEBOOK STORE UYGULAMASI

Google Dokümanları Kullanmak

MS Publisher Kullanım Hatırlatmaları

Windows 10 için Java JDK 8 ve NetBeans IDE 8.2 Kurulumu Detaylı Anlatım

Java 2 Standart Edition SDK Kurulum ve Java ya Giriş

Ecat 8. Hakbim Bilgi İşlem A.Ş. Versiyon

T.C. istanbul ÜNiVERSiTESi ÖĞRENCi BiLGi SiSTEMi. ÖĞRETiM ELEMANI KULLANIM KILAVUZU

Samsun Çocuk Hizmetleri İ l Koordinasyon Sekretarya Birimi

2-Hafta Temel İşlemler

TEMEL BİLGİSAYAR. Ders Notları. Yrd. Doç. Dr. Seyit Okan KARA

Web sayfalarında yapılan her çalışma ve düzenleme tablolar aracılığı ile yapılır. Dolayısıyla çoğu web sayfalarında tablo kullanmak zorunluluktur.

2. HTML Temel Etiketleri

BİL BİLGİSAYAR PROGRAMLAMA (JAVA)

BİLGİSAYARDA OFİS PROGRAMLARI BİÇİMLENDİRME

Hizalama Word dokümanlarınızda oluşturduğunuz veya oluşturacağınız metinlerin hizalamasını yapabilirsiniz. Bu işlem için:

Kullanım Kılavuzu

MİCROSOFT WORD PROGRAMI ÇALIŞMA KAĞIDI

BEUN VPN Hizmeti. VPN Nedir?

YILDIZ TEKNİK ÜNİVERSİTESİ

Xilinx ISE Webpack 14.7 Kurulum Tutorial

UYGULAMALAR. İkinci liste kutusu (List 2) Birinci liste Kutusu (List 1) Metin Kutusu

ÜNİTE ÜNİTE MICROSOFT POWER POINT - I TEMEL BİLGİ TEKNOLOJİLERİ İÇİNDEKİLER HEDEFLER

4. Bağlantı (Köprü) Oluşturma

e-imzatr Kurulum Klavuzu

İdari Birimler Yönetim Paneli Kullanma Kılavuzu Bilgi İşlem Daire Başkanlığı Web Tasarım Ve Yazılım Birimi

WAMP SERVER KURULUMU

Elektronik Belge Yönetim Sistemi Kullanım Kılavuzu

7. Çerçeveler. Bu bölümü bitirdiğinizde,

Problem Yaklaşım Temelleri, Algoritma ve Akış Şeması

BLM401 Mobil Cihazlar için ANDROİD İşletim Sistemi KULLANICI ARAYÜZ. BLM401 Dr.Refik SAMET

Açılan programın pencere görünümü aşağıdaki gibidir. 2. Araç Çubuğundan kaydet düğmesi ile

WORD KULLANIMI

ÇANKIRI KARATEKİN ÜNİVERSİTESİ ZİMBRA E-POSTA SİSTEMİ KULLANICI DOKÜMANI

1) İlk olarak oluşturduğumuz filtre adı yazılır. (örneğin tatil mesajı, taşı vb gibi.) 2) Sonra filtre için kural belirlenir.

4.1. Grafik Sihirbazını kullanarak grafik oluşturma

C için tümleşik geliştirme ortamı (IDE) kurulumları

SIMAN KULLANIM KILAVUZU

HTML Bloklar. CSS Display özelliği

AEGEE-Eskişehir Online Web Yönetim Paneli ( WEBBY ) Yardım Dökümanı

INTERNET BAĞLANTISININ KURULMASI İÇİN GEREKLİ YÖNLENDİRİCİ AYARLARI

Dinamik Kodlama. [X] [X] Yeni Fonksiyon

16. Kesit ve Cephe Aracı

SM 100 Terazi Ayarları. Digi SM 100. SM 100 Terazi Ayarları

ASP.NET ile Bir Web Sitesi Oluşturma

NECMETTİN ERBAKAN ÜNİVERSİTESİ E-POSTA YARDIM BELGESİ

iphone & ipad için e-posta hesabı kurulumu

GRAFİK TASARIM. ACTION SCRIPT 3.0 Ders1 YARD. DOÇ. DR. MEHTAP YALÇINKAYA

Daha önce bu işlemin iki tane dosya oluşturduğunu gördük. GecDenTest.aspx dosyasının source kısmında içeriğini inceleyecek olursanız en başta

NOT: BU BELGEYİ OKUMADAN LÜTFEN YAZILIMI YÜKLEMEYE ÇALIŞMAYIN.

E-Posta Hesabı Oluşturma

MPLAB PROGRAM GELİŞTİRME ORTAMINDA CC8E İLE KOD HAZIRLAMA HAZIRLAYAN: DOÇ. DR. HAMİT ERDEM ARAŞ. GÖR. GENCER TULAY

Linux Kurulumu (Sürüm 1.52) İçindekiler

YILDIZ TEKNĠK ÜNĠVERSĠTESĠ

MEB E-Posta Hizmetleri ve Outlook Programı

Temel Bilgisayar Terimleri Yrd. Doç. Dr. Devkan Kaleci

İŞLETMELERDE BECERİ EĞİTİMİ DERSİ MİCROSOFT WORD 2007 ÇALIŞMALARI

Java Programlamaya Giriş

LİGHTKOD SETUP MAKER KULLANIMI 1- Giriş Programı yükledikten sonra Setup Maker programını açtığımızda aşağıdaki pencereyi görürüz. Burada 1.

ArahWeave Dobby Hızlı Başlangıç

Kaynak Kodlardan Derleme. Turquaz Muhasebe. Versiyon 0.2. Hüseyin Ergün. 26 Mart 2005

POWER POİNT 2007 DERS NOTLARI

24 Kasım 2011 / Perşembe

GtkD ile Görsel Programlama

B2B Sistemi Kullanımı Hakkında Bilgiler

Windows form uygulamalarından alışık olduğumuz sabit piksel koordinatları, WPF ile son buldu. WPF uygulamaları farklı çözünürlüklerde çalışsalar bile

Windows XP Professional Kurulumu

ÇANKAYA ÜNİVERSİTESİ WEBMAIL KULLANIM KLAVUZU

Kurumsal Grup E-Posta Eğitim Dokümanı

MİCROSOFT POWER POINT 2007 DERS NOTLARI GİRİŞ SEKMESİ

Açılan penceren gerekli ayarlamalar yapılarak sayfa numaraları görüntülenir.

OfficeExcelProgramıAnlatımı

4 Front Page Sayfası Özellikleri

DIV KAVRAMI <style> position: absolute

Karabük Üniversitesi, Mühendislik Fakültesi...

HSancak Nesne Tabanlı Programlama I Ders Notları

OKUL HABER EKLEME MODÜLÜ TANITIM DOSYASI. Okul haberlerinizi ilçemiz web sitesinde yayınlayabilmek için aşağıdaki adımları uygulamanız gerekmektedir.

TAKSİ-DURAK MÜŞTERİ TAKİP PROGRAMI

Makey Oz Modülünü Bilgisayardan Programlamak Uygulama Kurulumu

Turquaz Windows kurulum dökümanı. ftp://ftp.mirror.ac.uk/sites/ftp.postgresql.org/binary/v7.3.1/windows/pgsql731wina1.exe

SIEMENS NX CAE YAZILIMLARI İÇİN COMPOSITE HOST ID VE MAC ADRESİ NASIL ÖĞRENİLİR?

Çözüm Bilgisayar. Çözüm İntSite

Transkript:

Kivy Mobil Programlama Sürüm 0.1 Mustafa Başer 30 May 2016

İçindekiler 1 Giriş 3 1.1 Kivy Hakkında.............................................. 3 1.2 Belge Hakkında............................................. 3 1.3 Ne Bilmeliyim?............................................. 4 1.4 UYARI.................................................. 4 2 Kivy nin Kurulumu 5 2.1 Windows da Kurulum.......................................... 5 2.2 Linux da Kurulum............................................ 6 3 Temel Bilgiler 7 3.1 Merhaba Dünya............................................. 7 3.2 Pencere Düzenleri............................................ 8 4 Kivy Dili: kv (kv lang) 15 4.1 Merhaba Dünya yeniden........................................ 15 4.2 Kutu Pencere Düzeni (Box Layout)................................... 15 4.3 Izgara Pencere Düzeni (Grid Layout).................................. 17 4.4 Parçacık Boyutları (size_hint)...................................... 18 4.5 İkisi Bir Arada.............................................. 19 5 Olaylar ve Popup 21 5.1 İşaret Dili (markup)........................................... 23 5.2 Popup Pencere: (popup)......................................... 25 6 Metin Düzenleyici 31 6.1 Ana Pencere............................................... 31 6.2 Farklı Kaydet............................................... 32 6.3 Kaydet.................................................. 38 6.4 Aç.................................................... 39 6.5 Yeni.................................................... 42 6.6 Çıkmadan Önce............................................. 44 7 Paketleme 47 7.1 Buildozer Kurulumu........................................... 47 7.2 Paket Derleme.............................................. 48 7.3 İmzalama................................................. 49 7.4 Sanal Linux Makina........................................... 52 i

8 Atlıkarınca ve Resim Gösterici 59 8.1 Atlıkarınca (Carousel).......................................... 59 8.2 Resim Gösterici............................................. 60 9 Dizinler ve Tablolar 67 ii

İçindekiler: İçindekiler 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: Mon May 30 04:28:06 2016 1.2.2 Belgeye katkıda bulunanlar Mustafa Başer 3

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: 012012setx 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: 012012 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): 012012 python \PYGZhy{}m pip install docutils pygments pypiwin32 kivy.deps.sdl2 kivy.de 3. Ve son olarak Kivy i kuralım: 5

012012 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. 012012\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: 012012\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 leftleft@default11@default11@default 012012 \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: 7

Şekil 3.1: Merhaba Dünya 012012\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: 012012\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: 012012\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: 012012\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 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 leftleft@default11@default11@default 012012 \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.gridlayout} \PYG{k+kn}{import} \PYG{n}{GridLayout} \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}{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

\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 cols2 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 leftleft@default11@default11@default 012012 \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

\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

Liste 3.4: girisformu.py leftleft@default11@default11@default 012012 \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+ \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

\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

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 leftleft@default11@default11@default 012012 \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ı girisformu1 programını kaydettiğiniz aynı dizinine (klasöre) kaydedin. 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 girisformu1 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. 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 15

düzeni BoxGridLayout() sınıfı ile oluşturulur. O halde kv dilinde BoxLayout ile kutu pencere düzenini oluşturabiliriz. Liste %s deki gibi değiştirin. 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.2 deki gibi eklemelisiniz. Liste 4.2: girisformu.kv leftleft@default11@default11@default 012012 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. Şekil 4.2: Kutu Pencere Düzeni: Dikey Yönelimli 16 Bölüm 4. Kivy Dili: kv (kv lang)

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.3 deki gibi yazın. Metin kutularının TerxtInput ile oluşturulduğuna dikkat etmelisiniz. Liste 4.3: girisformu.kv leftleft@default11@default11@default 012012 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 yerleştirilmiş (dikey yönelimli), yatay yönelimli kutulardan oluşmaktadır. Liste 4.4 yi inceleyin. Liste 4.4: girisformu.kv leftleft@default11@default11@default 012012 BoxLayout: orientation: \PYGZdq{}vertical\PYGZdq{} BoxLayout: Label: text: \PYGZdq{}Kullanıcı Adı:\PYGZdq{} TextInput: BoxLayout: Label: text: \PYGZdq{}Parola:\PYGZdq{} TextInput: 4.3. Izgara Pencere Düzeni (Grid Layout) 17

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.4 ve Liste 4.3 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.4 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.3 deki gibi düzenleyelim. leftleft@default11@default11@default 012012 BoxLayout: orientation: \PYGZdq{}vertical\PYGZdq{} Liste 4.5: girisformu.kv 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: \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 18 Bölüm 4. Kivy Dili: kv (kv lang)

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.6 de bunu görüyorsunuz. Liste 4.6: main.py leftleft@default11@default11@default 012012 \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:} 4.5. İkisi Bir Arada 19

\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 012012\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: 012012\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 leftleft@default11@default11@default 012012 \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

argüman olarak gönderilir. Aslında dugme yi self in özelliği yapmadan, gelen nesne üzerinden de metni değiştirebilirdik: 012012\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 leftleft@default11@default11@default 012012 \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 leftleft@default11@default11@default 012012 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 leftleft@default11@default11@default 012012 \PYG{k+kn}{from} \PYG{n+nn}{kivy.app} \PYG{k+kn}{import} \PYG{n}{App} 22 Bölüm 5. Olaylar ve Popup

\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 leftleft@default11@default11@default 012012 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

etiket tanımlamış olsaydık, işaret dilini etkinleştirmek için 012012\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: 012012\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: 012012\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 [fontdejavuserif.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

[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 leftleft@default11@default11@default 012012 \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: 012012\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 leftleft@default11@default11@default 012012 \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

\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_downpopup.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_dismissfalse 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 leftleft@default11@default11@default 012012 \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

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: 012012\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

Liste 5.9: main.py leftleft@default11@default11@default 012012 \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. 28 Bölüm 5. Olaylar ve Popup

Şekil 5.4: Popup işevinden Ana Penceredeki metnin değiştirilmesi. Artık basit bir uygulama yazabiliriz. Şu can sıkıcı ve hiçbir işe yaramayan Metin Düzenleyici yazacak kadar bilgi sahibi olduk. 5.2. Popup Pencere: (popup) 29

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 leftleft@default11@default11@default 012012 \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

Liste 6.2: metinduzenleyici.kv leftleft@default11@default11@default 012012 \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ı 012012\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

Şekil 6.1: Metin Düzenleyicimiz Kullanıma Hazır :-) 6.2. Farklı Kaydet 33

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 leftleft@default11@default11@default 012012 \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: 012012\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. 012012\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

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): 012012Button: 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: 012012\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 (FakrliKaydet- Form de 12. satırı aşağıdaki gibi değiştirin): 012012on\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: 012012\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

Şekil 6.2: Farklı Kaydet Penceresi 36 Bölüm 6. Metin Düzenleyici

\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: 012012on\PYGZus{}press: app.farkikaydetislevi(root); root.dismiss() Gelelim farkikaydetislevi() işlevine: bu işlevi build() den hemen önce şu şekilde tanımlayabiliriz: 012012\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): 012012\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

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: 012012\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: 012012\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 012012\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: 012012on\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

012012\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: 012012\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: 012012\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: 012012\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: 012012\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

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 leftleft@default11@default11@default 012012 \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: 012012\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: 012012on\PYGZus{}press: app.dosyaacislevidialog() Şimdi de bu işlevi tanımlamak gerekiyor. build() den hemen önce işlevimizi şöyle tanımlayabiliriz: 012012\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

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: 012012\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: 012012\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 leftleft@default11@default11@default 012012 \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

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: 012012\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: 012012\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: 012012\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

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 (metin_duzenleyici_metin_duzenleyici_kv1) 23. satırı şu şekilde değiştirmemiz gerekmektedir: 012012on\PYGZus{}press: app.yenidosyaacislevi() Bu işlevi de build() den önce şu şekilde yazabiliriz: 012012\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 leftleft@default11@default11@default 012012 \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: 012012\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. 6.5. Yeni 43

012012\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: 012012\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: 012012Button: 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: 012012\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. 44 Bölüm 6. Metin Düzenleyici

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 kaydedilmemiş olacak. O halde programımız içerisinde 012012\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: 012012\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 012012\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: 012012\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: 012012\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 leftleft@default11@default11@default 012012 \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 6.6. Çıkmadan Önce 45

BoxLayout: 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: 012012\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: 012012\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 gö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: 012012\PYG{g+gp}{\PYGZsh{}} apt\pygzhy{}get install git Yazılım havuzundan indirelim: 012012\PYG{g+gp}{\PYGZsh{}} git clone https://github.com/kivy/buildozer.git Kurulumu gerçekleştirelim: 012012\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: 012012\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

012012\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: 012012\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?exportdownload&confirmser1&id0b3-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: 012012\PYG{g+gp}{\PYGZdl{}} buildozer init Daha sonra buildozer.spec dosyasını düzenleyelim. Ben sadece aşağıdaki değişiklikleri yaptım: 012012\PYGZsh{} (str) Title of your application title Kivy Metin Duzenleyici \PYGZsh{} (str) Package name package.name kiviymetinduzenleyici Şimdi de sıra paketlemeye geldi: 012012\PYG{g+gp}{\PYGZdl{}} buildozer android release Şu şekilde başlaması gerekiyor: 012012\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

\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ütefn 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: 012012\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

Şekil 7.1: Anahtar Dosyası 50 Bölüm 7. Paketleme

Şekil 7.2: Anahtar Oluşturma Şekil 7.3: APK Paketini imzalama 7.3. İmzalama 51

Son olarak Sign düğmesine tıklayın. Şimdi MetinDuzenleyici/bin/KivyMetinDuzenleyici-0.1-release- SIGNED_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?exportdownload&confirmser1&id0b3-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,20pt20pt@default20pt20pt@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ğ paneldeki20pt20pt@default20pt20pt@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

Şekil 7.4: Makina mimarisi seçimi Şekil 7.5: Sanal makinenin belleğini belirleme 7.4. Sanal Linux Makina 53

Ş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): 012012\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: 012012\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

Şekil 7.7: Sanal makine için paylaşım açma 7.4. Sanal Linux Makina 55

Şekil 7.8: Linux Sanal Makine 56 Bölüm 7. Paketleme

012012\PYG{g+gp}{\PYGZdl{}} mcedit buildozer.spec Deneme derlemesi için sadece aşağıdaki değişiklikleri yapın 012012\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. 012012\PYG{g+gp}{\PYGZdl{}} buildozer android release şu şekilde başlaması gerekiyor: 012012\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

58 Bölüm 7. Paketleme

BÖLÜM 8 Atlıkarınca ve Resim Gösterici Uyarı: Bu bölüm taslak aşamasındadır. 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 leftleft@default11@default11@default 012012 \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 59

\PYG{k}{return} \PYG{n}{karinca} \PYG{n}{atliKarinca}\PYG{p}{(}\PYG{p}{)}\PYG{o}{.}\PYG{n}{run}\PYG{p}{(}\PYG{p}{)} 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. 60 Bölüm 8. Atlıkarınca ve Resim Gösterici

Liste 8.2: resimgosterici.kv leftleft@default11@default11@default 012012 \PYGZlt{}resimGosterici\PYGZgt{}: Bo orientation: \PYGZdq{}vertical\PYGZdq{} Carousel: size\pygzus{}hint\pygzus{}y: 9 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 leftleft@default11@default11@default 012012 \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 leftleft@default11@default11@default 012012 \PYG{c+c1}{\PYGZsh{} \PYGZhy{}*\PYGZhy{} coding: utf\pygzhy{}8 \PYGZhy{}*\PYGZhy{}} 8.2. Resim Gösterici 61

Şekil 8.2: Basit Resim Gösterici (kaydırırken) \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}{:} \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 leftleft@default11@default11@default 012012 \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} 62 Bölüm 8. Atlıkarınca ve Resim Gösterici

\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}{resimleriEkle}\PYG{p}{(}\PYG{n+nb+bp}{self}\PYG{p}{,} \PYG{n}{dosyalar}\P \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{ \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{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 17. satırı şu şekilde de yazabilirdiniz: 012012\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: leftleft@default11@default11@default 012012 \PYGZlt{}acForm\PYGZgt{}: size\pygzus{}hint: (.9,.9) Liste 8.6: acform BoxLayout: orientation: \PYGZsq{}vertical\PYGZsq{} FileChooserIconView: size\pygzus{}hint\pygzus{}y: 9 filters: [\PYGZsq{}*.*\PYGZsq{}] path: app.son\pygzus{}patika multiselect: True BoxLayout: size\pygzus{}hint\pygzus{}y: 1 id: dosya\pygzus{}secim Button: 8.2. Resim Gösterici 63

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: 012012\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. 012012\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: 012012\PYGZlt{}resimGosterici\PYGZgt{}: BoxLayout: orientation: \PYGZdq{}vertical\PYGZdq{} Carousel: size\pygzus{}hint\pygzus{}y: 9 id: karinca BoxLayout: size\pygzus{}hint\pygzus{}y: 1 text: \PYGZdq{}Aç\PYGZdq{} on\pygzus{}press: app.klasorac() 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: 012012\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 devam edecek... 64 Bölüm 8. Atlıkarınca ve Resim Gösterici

Şekil 8.3: Dosya veya Klasör Seçimi 8.2. Resim Gösterici 65