7 Ocak 2011 Cuma

RubyQt ile Küçük Bir Zamanlayıcı

Özgürlük İçin... Pardus...
Qt Designer ile Ruby program denemelerim devam ediyor. Daha önce wxRuby ile yaptığım ve çok kullandığım bir uygulamayı Qt designer ile yapmaya karar verdim. Zamanlayıcı uygulamasını işlerimi "multitasking" yönetebilmek için tasarlamıştım. Program aslında çok basit bir geri sayıcı, ayarlanan süre sonunda beni uyarsın diye kuruyorum. Verilen süreyi geriye doğru saydıktan sonra sıfıra gelince uygulama penceresini minimize edip büyüterek uyarıyor. Faydalı bir eser , aynı işte takılıp kalmamı engellemek için kullanıyorum.

Öncelikle QT Designer ile timer.ui adında bir arabirim hazırlamamız gerekiyor. Yeni arabirimi QWidget olarak seçip designer'ı başlattıktan sonra, form boyutlarını 260x260 olarak değiştiriyoruz. Formun boyutunun değişmesini istemediğmiz için minimumSize ve maximumSize özelliklerini de 260x260 olarak ayarlıyoruz. Formun arkaplan rengini değiştirmek için "styleSheet" özelliği yanındaki (...) düğmesini tıklayarak açılan pencerede, "Add Color" yanındaki dropdown listeden "background-color" seçiyoruz ve RGB olarak (128,255,255) cyan rengi ayarlıyoruz.


Şimdi aşağıdaki objeleri gösterilen isim, konum ve boyutlarla yerleştirelim.
Kısaca özetlersek, sayılacak zamanı saat ve dakika olarak 2 spinbox üzerinden gireceğiz. Baştan Başla isimli düğmeye tıklayınca süremiz spinbox'larda belirtilen değerden geriye doğru symaya başlayacak. Kalan süre ortadaki kocaman label'da (result_text) görünecek. Uygulamaya benim daha sonra eklediğim 4 düğme de spinbox'lara sık kullanılan zaman değerlerini kısa yoldan yüklemek için kullanılacak.
Maalesef uygulamamızda designer üzerinden ayarlayıp işi bitireceğimiz SIGNAL-SLOT bağlantıları yok, tüm button'lar bizim yazacağımız script'leri çağıracak. Şimdi forma SLOT'lar ekleyip button'larımızı bunlara bağlayacağız. Forma nasıl kendi SLOT'umuzu ekleyeceğimizi qt-designer-bolum-2 yazımızda görmüştük. Ekleyeceğimiz SIGNAL-SLOT bağlantıları şöyle :
button_15_min, SIGNAL(clicked()), Form, SLOT(button_15_clicked())
button_30_min, SIGNAL(clicked()), Form, SLOT(button_30_clicked())
button_45_min, SIGNAL(clicked()), Form, SLOT(button_45_clicked())
button_1_h, SIGNAL(clicked()), Form, SLOT(button_1_clicked())
pushButton, SIGNAL(clicked()), Form, SLOT(restart()))
Designer ile işimiz bu kadar, artık Ruby kodlamaya geçebiliriz. timer.ui dosyasını kaydedip çıkalım. Şimdi komut satırında :
rbuic4 -x -o timer.rb timer.ui
yazalım ve görselimize karşı gelen Ruby dosyasını üretelim. Dosyayı önceki yazımızdaki gibi düzenleyip slotlara karşı metodları tanımlayalım.

require 'timer'

class MyWidget < Qt::Widget
 slots 'button_15_clicked()', 'button_30_clicked()', 'button_45_clicked()',  
           'button_1_clicked()', 'restart()'
 def initialize parent=nil
  super
  @base=Ui_Form.new
  @base.setupUi self
 end
 
 def button_15_clicked
 
 end

 def button_30_clicked
 
 end

 def button_45_clicked
 
 end

 def button_1_clicked
 
 end
 
 def restart
 
 end
end


    about = KDE::AboutData.new("form", "Form", KDE.ki18n(""), "0.1")
    KDE::CmdLineArgs.init(ARGV, about)
    a = KDE::Application.new
    #u = Ui_Form.new
    w = MyWidget.new
    #u.setupUi(w)
    a.topWidget = w
    w.show
    a.exec
Şimdi hatasız çalışır ama butonlara tıklamak şimdilik birşey yapmıyor. Ortadaki dört butonun yaptığı iş basit, spinbox'ların içine kestirmeden değer yazıyorlar önce onları düzenleyelim :

 
 def button_15_clicked
  @base.hour_spin.setValue 0
  @base.minute_spin.setValue 15
 end

 def button_30_clicked
  @base.hour_spin.setValue 0
  @base.minute_spin.setValue 30
 end

 def button_45_clicked
  @base.hour_spin.setValue 0
  @base.minute_spin.setValue 45
 end

 def button_1_clicked
  @base.hour_spin.setValue 1
  @base.minute_spin.setValue 0
 end
 
Çalıştırıp orta sıradaki butonların spinbox'lara değer yazdığını test edelim. İlk çalışmada default olarak 1 saat set edilmesi için "initialize" metodunda "button_1_clicked" çağrılmalıdır. Zamanlama yapmanın koşulu timer kullanmak. QtRuby'de zamanlayıcı Qt::Timer sınıfı ile üretilir. Yeni bir zamanlayıcı üreteceğiz, bunun tıklamasını 1000 ms(1 saniye) ayarlayacağız ve zamanlayıcı çıkış verince çalışmasını istediğimiz rutin için bu zamanlayıcının "timeout()" sinyalini bizim tanımlayacağımız "timeout_block()" metoduna bağlayacağız. Daha sonra da zamanlayıcımızı çalıştırıp, sayacağımız değeri spinbox'lardan alacağımız "restart" rutinini çağıracağız. Bunun için "initialize" metodunu şöyle değiştiriyoruz :
def restart
  @sayac = @base.hour_spin.value * 3600 + @base.minute_spin.value * 60
  @bitti = false
  @bitti_sayac = 0
 end
İlk satır saniye olarak değeri hesaplayıp geri sayım sayacına bunu yazıyor. 2. satırda süre bitince saymayı bırakıp animasyona geçtiğimizin bilgisini saklayan değişkeni sıfırlıyoruz. Son satırdaki sıfırladığımız sayacı da animasyon için kullanacağız. Sırada "timeout_block" metodumuz var.


 def timeout_block
  @bitti = true if @sayac == 1
  @sayac -= 1
  @sayac = 0 if @sayac<0
  @base.result_text.text = ("%02d" % (@sayac/60).to_s) + ":" + ("%02d" % (@sayac%60).to_s)
  
  @bitti_sayac += 1 if @bitti

  if ((@bitti_sayac<5) or ((@bitti_sayac%5) == 0)) and @bitti
   windowState==0 ? showMinimized : showNormal
  end
 end
1. satır geri sayımın son saniyesinde sayımın bittiğini belirliyor. 2. satır geri sayım işlemi, bu rutine her gelindiğinde 1 saniye geçmiştir ve sayacı 1 eksiltmek gerekir. 3. satırda sayacın eksiye gitesi engelleniyor, çoook uzun zaman geçince sayı negatiften devir yapabilir diye önlem aldık. 4. satır kalan süreyi ortadaki kocaman label'a yazıyor ki kullanıcımız bakınca ne kadar süre kaldığını görsün. 5. satır süre bittiyse animasyon sayacımızı saydırıyor. Sonraki if bloğu da ilk 5 saniyede her seferinde sonrasında 5 saniyede bir uygulama penceresini aşağı indirip geri alıyor.
Artık minik timer ile oynayabiliriz. Ben bunu kurup bilgisayara dalıyorum, süre bitince beni ayıltıp dünyaya dönmem gerektiğini hatırlatıyor. Öğrenme yolunda faideli bir eser oldu ,
Hoşçakalın...

Hiç yorum yok:

Yorum Gönder