Selam WxRuby3 GUI kütüphanesi denemelerimize olay işleme teknikleri ile devam ediyoruz.
WxRuby'de Olaylar
Olaylar her GUI uygulamanın vazgeçilmez parçasıdır. Tüm GUI uygulamaları olay yönelimlidir. Bir uygulama çalıştığı müddetçe değişik olaylara tepki gösterir. Bir uygulamada olaylar genellikle kullanıcı tarafından oluşturulur. Ama başka şeyler de olay üretebilir, mesela internet bağlantısı, pencere yöneticisi veya zamanlama ile üretilen olaylar. Uygulamamızda run metodunu çalıştırdığımızda, uygulamamız olayların oluşmasını beklemeye başlar.
Tanımlar
Olay (Event) genelde GUI Toolkit tarafından sağlanan uygulama seviyesi bilgilerin bir parçasıdır. Olay döngüsü (Event loop) bir programdaki olayları veya mesajları bekleyen ve gönderen bir programlama yapısıdır. Olay döngüsü sürekli olarak işlenecek bir olay olmasını bekler. Dağıtıcı (dispatcher) olayları olay işleyicilerine eşleyen bir işlemdir. Olay işleyiciler (event handler) oluşan olaylara tepki gösteren metodlardır.
Olay nesnesi (event object) olayın gerçekleştiği nesnedir. Genellikle bir widget olur. Olay tipi (event type) ise gerçekleşen olayın kendisidir. Olay bağlayıcı (event binder) olay tipini olay işleyiciye bağlayan nesnedir.
evt_move örneği
Bu örneğimizde Wx::MoveEvent olayına tepki veren bir uygulama yapacağız. Bu olay pencereyi başka bir pozisyona hareket ettirdiğimizde oluşur. Bu olay için bağlayıcı Wx::EVT_MOVE'dur.
simple_event.rb
Örneğimiz pencerenin ekrandaki pozisyonunu gösteriyor, yani penceremizin sol-üst köşesinin ekranımızın sol-üst köşesine göre koordinatları.
EventHandler sınıfından gelen evt_move metodu bir olay bağlayıcısı Wx::EVT_MOVE olayını kullanıcının tanımlayacağı on_move metoduna bağlar. evt_move metoduna istersek bir kod bloğunu argüman olarak vererek olay işlemesini orada da yapabiliriz.
gibi.
on_move metoduna parametre olarak gelen e nesnesi gerçekleşen olayı ifade eden nesnedir. Örneğimize bakarsak Wx::MoveEvent nesnesi. Şu andaki pozisyonu olay nesnesinin get_position metodu ile okuruz.
WxRuby olayları bağlamak
Bir olayı işlemenin 3 adımı vardır.
- Olay tipini belirlemek. Dokümandan yararlanabiliriz.
- Bir olay işleyici blok ya da metod hazırlamak
- Bu bloğu ya da metodu EventHandler metodlarını kullanarak olaya bağlamak
Yukarıdaki örnekteki olayımız Wx::EVT_MOVE olayı ve bağlayıcı metodunun dökümanda tanımı şöyle:
Bu yapı bize iki olasılık veriyor, ya bir metod ismi vererek olay gerçekleşince o metodun çağrılmasını sağlıyoruz, ya da bir kod bloğu içinde direk olarak hemen orada olayı değerlendiriyoruz. Metod ismi verirken sembol veya string değer kullanabiliriz. Böyle sabit yazı değerler için genelde sembol kullanılır, çünkü hafıza kullanımı daha az. Metod ya da bloğa geçen argüman ise Wx::MoveEvent olay nesnesinin kendisi, yani gerçekleşen olay bilgisi.
Olayı veto etmek
Bazen uygulamamızın bir olaya tepki vermesini engellemek isteriz, bu amaçla veto metodu kullanılır.
event_veto.rb
Örneğimizde Wx::CloseEvent olayını işliyoruz. Bu olay kullanıcı pencerenin çarpı butonuna tıklayıp kapatmaya kalkınca ya da Alt+F4 basınca ya da menüden çıkış seçeneği seçilince oluşur. Çoğu uygulamada kaydedilmemiş verilerin kaybedilmemesi için kapatma işlemi engellenerek mesaj gösterilir.
CloseEvent olayını on_close_window metoduna bağlıyoruz.
Kapatma olayını işlerken kullanıcıya bir diyalog mesajı gösteriyoruz.
Diyalogda Evet butonuna tıklandıysa destroy metodu ile bulunulan Frame kapatılıyor. Burada destroy çağırmak zorundayız, eğer close metodunu kullanırsak olayı tekrar tetikler sonsuz döngüye gireriz.
WxRuby olay yayılımı
2 tür olay vardır, temel olaylar ve komut olaylar. Bunların yayılımı farklı olur. Olay yayılımı elemandan ebeveynine , oradan da dedesine doğru olur. Temel olaylar yayılmazken, komut olaylar yayılır. Örneğin Wx::CloseEvent bir temel olay. Bir elemanda bu olay oluşursa ebeveyn elemanına yayılmaz.
Default olarak olay işleyicisi tarafından işlenen bir olay yayılımını durdurur. Yayılıma devam etmek için skip metodu kullanılmalıdır.
event_propagation.rb
Öncelikle evt_left_down olay bağlayıcısını kullanıyoruz, çünkü hem panel hem frame hem de button bu olaya tepki verir. Ancak bu olay normalde yukarı doğru yayılmaz, bu yüzden her kontrolün olay işleyicisine e.resume_propagation 1 satırını ekledik ki bir yukarıya olay yayılabilir olsun.
skip metodu ise olayın yayılmaya devam etmesini sağlıyor, o olmasa ilk önce button olayı işler ve yukarı yayılma dururdu çünkü olaya tepki verildi. Şimdi çalıştırıp butona tıklarsak hangi sırada olayın yayıldığını konsolda görebiliriz.
Window ID'leri
WxWidgets kütüphanesinde görsel elemanlar (pencere, buton, yazı kutusu vs) genelde Wx::Window sınıfının alt sınıfları olduğu için window olarak da adlandırılıyor. Bu window'lara ait ID değerleri elemana ait olayların işlenmesinde kullanılır. Bir eleman ID'sini belirlemenin üç yolu vardır.
- Sistemin otomatik ID vermesi için bırakmak
- Standart ID değerlerinden kullanmak
- Kendi ID numaramızı vermek
ID değeri olarak -1 ya da Wx::ID_ANY vermek ID değerini WxRuby sistemine bırakmak demek oluyor. WxRuby kendi kafasına göre bunlara ayrı ayrı ID sayıları uyduracaktır. Otomatik verilen ID değerleri her zaman negatif olur, yani biz kendimiz ID veriyorsak mutlaka pozitif sayı vermeliyiz ki otomatiklerden birine kazara denk gelmesin.
Genelde otomatik ID yöntemini program içinde pek değiştirmeyeceğimiz elemanlar için kullanırız, mesela StaticText nesneleri pencerede sabit bir şeyler yazmak için kullanılır. Ama otomatik de verilmiş olsa hala elemanın ID değerini get_id metodunu çağırarak öğrenebiliriz.
default_ids.rb
Bu örnekte exit_button nesnesinin ID değerini bilmemize gerek yok, evt_button metoduna nesneyi tanıtırken get_id metodu ile ID değerini verebiliriz.
Aslında WxRuby diğer Wx uyarlamalarından biraz daha avantajlı evt_button metoduna ille de ID vermek zorunda değiliz direk nesneyi de verebiliriz.
Bu satır da sağlıklı çalışır.
WxRuby standart ID'ler
Standart ID'ler değişik platformlarda görsel ya da davranışsal avantajlar sağladığı için tercih edilmesi önerilir.
Kayıtlı bazı standart ID'ler vardır, örneğin Wx::ID_SAVE veya Wx::ID_NEW
standart_ids.rb
Örneğimizde standart ID kullanan butonlar var, bu butonlar etiketlerinde ne yazılacağını bildirmediğimiz halde sistemden etiketlerini otomatik alırlar, Linux sistemlerde butonların ikonları da olur. Bunların bir listesi WxWidgets dokümanında mevcut.
Wx::ID_EXIT ID değerine sahip butona tıklanınca uygulamanın kapatılmasını istiyoruz. Bu üzerinde Quit yazan buton.
Kendi ID değerlerimiz
Son seçeneğimiz kendi verdiğimiz ID değerleri ile çalışmak. Kendi global ID değerlerimizi tanımlıyoruz.
custom_ids.rb
Örnekte 3 elemanlı bir menü tasarlıyoruz ve menü elemanlarının ID'lerini kendimiz ürettik .
new_control_id metodu yeni bir benzersiz ID numarası üretir.
3 menü elemanını ID değerleri ile aynı olay işleyiciye ( mesaj_göster ) yönlendiriyoruz.
Olay nesnesinden olayın gerçekleştiği menü elemanının ID değerini get_id metodu ile çekiyor ve hangi menünün tıklandığını anlıyoruz. Buna göre de durum çubuğuna bir mesaj yazdırıyoruz.
Wx::PaintEvent
Paint olayı bir window tekrar çizildiğinde oluşur. Pencere boyutu değiştirdiğimizde ya da maximize ettiğimizde paint olayı oluşur. Paint olayını kodla da oluşturabiliriz. Örneğin bir Wx::StaticText nesnesinde set_label metodunu çağırarak. Not pencereyi minimize ettiğimizde paint olayı oluşmaz (çünkü pencere küçülmez ekrandan yok olur).
paint_event.rb
Örneğimizde penceremiz için oluşan paint olaylarını sayıyoruz. Konsola olay oluştuğu anda yazı yazılırken pencere üzerine yazılan yazının ancak pencereyi minimize ve restore edince yazıldığını görüyoruz. Çünkü Windows sistemi ancak o zaman son hali çiziyor. Başka işletim sistemlerinde nasıl olacağını denemek lazım. Bir nokta da paint olayı pencere boyutunu büyütünce oluşuyor ama küçültürken oluşmuyor.
Penceremizin paint olayını on_paint metoduna bağlıyoruz.
Burada paint do |dc| bloğu bir kalıp. Pencerede geçici bir DC çizim nesnesi tanımlayıp bunda çizim yaparak pencerede görünmesini sağlıyor. WxWidgets kullanan başka programlama dillerinde bu işlem daha farklı yapılıyor.
Wx::FocusEvent
Fokus uygulalamızda odaklanılan nesneyi gösterir. Klavyeden değer girilen eleman veya clipboard'dan yapıştırma yapılan eleman fokus olunan elemandır. Fokus ile ilişkili iki olay vardır. Wx::EVT_SET_FOCUS olayı elemana fokuslanıldığında oluşur. Wx::EVT_KILL_FOCUS olayı eleman fokus kaybettiğinde oluşur. Fokus ya mouse tıklamasıyla ya da tuş girişleri ile değişir (genellikle Tab veya Shift+Tab).
focus_event.rb
Örneğimizde 4 tane panel var fokus alan panelin etrafı kırmızı çiziliyor.
Fokus olaylarını metodlara bağlıyoruz.
Paint olayı gerçekleştiğinde panel için en son @color rengiyle 5 piksel genişlikte çizgiyle bir çerçeve çiziliyor. Yani paint olayında her panelin etrafına çerçeve çiziliyor, sadece rengini değiştirerek fokuslu olanı belirtiyoruz.
Fokus alan panelin @color değeri kırmızı renge karşı gelen '#ff0000' yapılıyor ve refresh metodu çağrılarak pencere görünümü yenileniyor, bu durum da paint olayını otomatik olarak tetikler.
Bir panel fokus kaybedince onun @color değeri panelin arkaplan rengi olan '#b3b3b3' değeri yapılıyor ve refresh metodu çağrılarak çerçevenin yeniden çizilmesi sağlanıyor. Böylece sanki çerçeve yokmuş gibi görünüyor. Pencerede paneller arasında bir yere tıklarsak tüm panellerde çerçeve yok olacaktır.
Wx::KeyEvent
Klavyemizden bir tuşa bastığımızda Wx::KeyEvent olayı oluşur. Bu olay o anda fokuslanılmış olan widget'a gönderilir. 3 değişik tuş olayı vardır
En yaygın kullanımlardan biri Esc tuşu basılınca pencereyi kapatmaktır.
key_event.rb
Burada yapılan işi yapan metod
get_key_code metodu ile basılan tuşun kodu alınıyor, bu kod Wx::K_ESCAPE tuşu mu bakılıyor. Tuşların listesi dokümanda mevcut.
Bu klavye olaylarında can sıkıcı bir şey, pencereye bir Wx::Panel nesnesi eklersek (ki bu yerleşim için lazım oluyor)), bu olaylar engelleniyor, panel tuşları sömürüyor. Bunun üstünden gelmek için evt_char_hook metodu ile tuş basılmasını işleyebiliriz.
WxRuby Diyaloglar
Diyalog pencereleri modern bir GUI uygulamasının vazgeçilmez parçalarıdır. Bir diyalog bir'den fazla kişi arasında iletişim kurmak için yapılır. Bilgisayar uygulamasında ise diyalog uygulama ile iletişim kurmak için kullanılır. Diyalog veri girmek için, veriyi değiştirmek için, uygulama ayarlarını değiştirmek için vs. kullanılır. Diyaloglar uygulama ve kullanıcı arasında iletişim kurmak için önemlidir.
Mesaj kutuları, yazı fontu ya da renk seçme diyalogları gibi hazır diyalogları kullanacağımız gibi kendi diyaloglarımızı da tanımlayabiliriz.
Basit mesaj kutusu
Mesaj kutusu ile kullanıcıya küçük bir bilgi verilir. Mesela CD'ye yazarken işlem bitince bir bilgilendirme diyalog penceresi otomatik olarak açılır.
message_box.rb
Uygulamamız 3 saniye sonra bir mesaj penceresi açıyor.
Wx sınıfı message_box metodu bize bir mesaj kutusu açıyor. İlk argüman gösterilecek mesaj, ikinci ise diyalog penceresi etiketi. Sonra bayraklar geliyor, Wx::OK, Wx::YES, Wx::NO, Wx::CANCEL eklenebilen buton flagları, Wx::ICON_WARNING, Wx::ICON_ERROR, Wx::ICON_INFORMATION ise ikon tipleri.
Ön tanımlı diyaloglar
Ön tanımlı diyaloglar yazı gösterme, girdi alma, dosya yükleme ve kaydetme gibi amaçlar için hazırlanmış diyaloglardır.
Wx::MessageDialog
Mesaj diyalogları kullanıcıya mesaj göstermek için kullanılır. Yukarıdaki basit mesaj kutusundan daha esnektir. Diyalogda kullanılan butonları ya da ikonları değiştirebiliriz.
Bayrak | Anlamı |
---|---|
Wx::OK | OK-tamam butonunu göster |
Wx::CANCEL | CANCEL- iptal butonunu göster |
Wx::YES_NO | Yes,No - Evet,Haıyr butonunlarını göster |
Wx::YES_DEFAULT | Evet butonu default |
Wx::NO_DEFAULT | Hayır butonu default |
Wx::ICON_EXCLAMATION | Alarm ikonu göster |
Wx::ICON_ERROR | Hata ikonu göster |
Wx::ICON_HAND | Hata ikonu göster |
Wx::ICON_INFORMATION | Info ikonu göster |
Wx::ICON_QUESTION | Soru ikonu göster |
Bu bayraklar Wx::MessageDialog sınıfı ile kullanılır.
message_dialogs.rb
Uygulamamızda 4 butonu bir grid sizer içine yerleştirdik. Bu butonlar 4 değişik diyalog penceresi açıyor. Bu pencereleri değişik bayraklarla biçimlendirdik.
Mesaj diyaloğunun üretilmesi oldukça basit. Diyaloğun parent değerine nil girerek diyalog penceresinin üst seviye bir pencere olduğunu, başka bir pencerenin alt penceresi olmadığını bildiriyoruz. İki string argümandan ilki mesajı ikinci ise pencere etiketini belirtiyor. OK butonu ve bir hata ikonu olacağını bildiriyoruz. Son olarak da show_modal ile diyaloğu modal olarak gösteriyoruz (yani onu kapatmadan uygulamanın başka penceresine geçilemez).
About diyalog penceresi
Hemen her GUI uygulamasında bir about (hakkında) diyaloğu bulunur. Genellikle gösterilmesi Help menüsü altında bir menü ile sağlanır. Bu diyaloğun amacı kullanıcıya uygulama ve versiyonu hakkında bilgi vermektir. Bu günlerde bu diyaloglarda programın yazarı hakkında da bilgiler bulunabiliyor. Ayrıca uygulama lisansı hakkında da bilgiler içerir. Yapan firmanın ya da uygulamanın logoları da olabilir.
Bir hakkında diyaloğu oluşturmak için iki nesne kullanırız, bir Wx::AboutDialogInfo nesnesi ve Wx sınıfının metodu olan Wx.about_box metodu.
about_dialog.rb
Uygulamamızda "Hakkında" menü elemanı var ve tıklanınca diyaloğumuz açılıyor.
Normalde açıklama ve lisans yazıları uzun yazılar olabilir, böyle durumlarda bunları kod içine koymaktansa ayrı bir dosya içinde yazmak daha doğru olur. Örneğin uygulamamızı başka dillere çevireceksek bu daha da gerekli olur.
Öncelikle bir Wx::AboutDialogInfo nesnesi üretiyoruz. Başlangıçta içi boş. Üretim metodu parametre almıyor.
Daha sonra penceremizde gösterilecek bilgileri düzenliyoruz.
Wx sınıfının about_box metodu ile info nesnemizi yani hakkında penceremizi görünür hale getiriyoruz.
Kendi diyaloğumuzun tasarımı
Şimdiki örneğimizde kendi diyaloğumuzu tasarlayacağız. Bir resim düzenleme uygulaması resmin renk derinliğini ayarlayabilir. Bu özelliği ifade edecek kendi diyaloğumuzu tasarlayalım.
custom_dialog.rb
Burada kendi tasarımımız bir diyalog oluşturduk
DerinlikDeğiştirDiyalog ismini verdiğimiz pencere sınıfımızı Wx::Dialog sınıfından kalıtımla oluşturduk.
Penceremizin bir oluşum nesnesini oluşturup show_modal metodunu çağırıyoruz. Pencereden çıkıldığında destroy metodunu çağırarak penceremizi yok ediyoruz.
Widget'lar
Sıra geldi benim zımbırtılara. WxRuby'nin temel zımbırtılarını göreceğiz inşallah. Her widget için küçük kod örnekleri yapacağız. Widget'lar Wx uygulamasının temel yapı taşlarıdır. Wx kütüphanesinde buton, checkbox, listbox, slider gibi geniş bir widget stoğu var.
Wx::Button
Wx::Button basit bir widget. Üzerinde bir etiket yazısı vardır ve tıklanınca bir hareketi tetikler.
button_wid.rb
Örnekte penceremizde tıklandığında uygulamayı kapatan bir "Kapat" butonu var.
Wx::Button sınıfı new metod yapısı
parent ve id değerleri sıralı verilmek zorunda diğerleri mesela pos: [20, 20] gibi key parametre olarak verilebilir. Burada sıralamaya uyduğumuz için isimlendirmeye gerek yoktur.
Olay işleme metodu evt_button butonumuza tıklandığını algılıyor ve uygulamadan çıkılmasını sağlıyor.
Hiç yorum yok:
Yorum Gönder