12 Mart 2025 Çarşamba

WxRuby3 ile Masaüstü Uygulama Geliştirmek 3

https://ujk-ujk.blogspot.com/2025/03/wxruby3-ile-masaustu-uygulama_12.html
İçindekiler +

 Selam WxRuby3 GUI kütüphanesi denemelerimize widget'ları inceleyerek devam ediyoruz.


Wx::ToggleButton

Wx::ToogleButton iki pozisyonu olan bir buton nesnesi: basılı ve basılı olmayan görünümleri var. Her tıkladığımızda bu iki durum arasında değişiyor. Bazen bu şekil çalışan butonlar lazım olur. 

Wx::ToggleBuuton.new metodunun parametreleri.

initialize(parent, id, label, pos = Wx::DEFAULT_POSITION,
  size = Wx::DEFAULT_SIZE, style = 0, val = Wx::DEFAULT_VALIDATOR,
  name = Wx::CHECK_BOX_NAME_STR)

parent, id ve label sıralı verilmek zorunda onları verdikten sonra diğerlerini sırası olmadan key parametre olarak verebiliriz.


toggle_buttons.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [350, 250]
    set_title "Wx::ToogleButton"
    centre

    pnl = Wx::Panel.new self

    @col = Wx::Colour.new 0, 0, 0

    rtb = Wx::ToggleButton.new pnl, Wx::ID_ANY, 'kırmızı', [20, 25]
    gtb = Wx::ToggleButton.new pnl, Wx::ID_ANY, 'yeşil', [20, 60]
    btb = Wx::ToggleButton.new pnl, Wx::ID_ANY, 'mavi', [20, 100]

    @cpnl  = Wx::Panel.new pnl, pos: [150, 20], size: [110, 110]
    @cpnl.background_colour = @col

    evt_togglebutton rtb, :toggle_red
    evt_togglebutton gtb, :toggle_green
    evt_togglebutton btb, :toggle_blue
  end
  def toggle_red(e)
    obj = e.get_event_object
    is_pressed = obj.get_value

    green = @col.green
    blue = @col.blue

    if is_pressed
      @col.set 255, green, blue
    else
      @col.set 0, green, blue
    end

    @cpnl.background_colour = @col
    @cpnl.refresh
  end
  def toggle_green(e)
    obj = e.get_event_object
    is_pressed = obj.get_value

    red = @col.red
    blue = @col.blue

    if is_pressed
      @col.set red, 255, blue
    else
      @col.set red, 0, blue
    end

    @cpnl.background_colour = @col
    @cpnl.refresh
  end
  def toggle_blue(e)
    obj = e.get_event_object
    is_pressed = obj.get_value

    red = @col.red
    green = @col.green

    if is_pressed
      @col.set red, green, 255
    else
      @col.set red, green, 0
    end

    @cpnl.background_colour = @col
    @cpnl.refresh
  end
end

Wx::App.run {
  Örnek.new(nil).show
}


Bu colour ve centre kelimeleri gerçekten canımı sıkıyor, niye center değil niye color değil de daha az kullanılan kelimeleri tercih etmişler. 

Bu uygulamada bir panel üzerinde kırmızı yeşil ve mavi seçebileceğimiz 3 toggle buton koyduk. 

    rtb = Wx::ToggleButton.new pnl, Wx::ID_ANY, 'kırmızı', [20, 25]

Üzerinde kırmızı yazan butonu oluşturuyor. Argümanlar sıralı verildiği için key parametre ihtiyacımız yok. 

    @cpnl  = Wx::Panel.new pnl, pos: [150, 20], size: [110, 110]
    @cpnl.background_colour = @col

Bu panelin rengini bizim butonlarımız değiştirecek.

    evt_togglebutton rtb, :toggle_red
    evt_togglebutton gtb, :toggle_green
    evt_togglebutton btb, :toggle_blue

Olay işleme metodları, evt_togglebutton ve ilk argümanda buton ya da butonun ID değeri, ikinci argümanda ise çağrılacak metod adı sembol olarak verilir. Metod çağırmayıp direk orada kod bloğu koyacaksak argümanlar tabi ki parantez içinde verilmeli.

    evt_togglebutton(rtb) { p "bişey" }

gibi.

  def toggle_red(e)
    obj = e.get_event_object
    is_pressed = obj.get_value

    green = @col.green
    blue = @col.blue

    if is_pressed
      @col.set 255, green, blue
    else
      @col.set 0, green, blue
    end

    @cpnl.background_colour = @col
    @cpnl.refresh
  end

Önce olaya sebep olan butonun basılı olmasını test edip is_pressed değişkenine kaydediyoruz. Daha sonra panelin mevcut olan yeşil ve mavi renk değerlerini alıp üzerine kırmızı yazılı butonumuzun basılı olup olmamasına göre rengin kırmızı bileşenini veriyoruz. Son olarak gösterge panelimizin rengini bulduğumuz değere eşitleyip, panelin refresh metodunu çağırarak tekrar boyanmasını sağlıyoruz.




Wx::StaticText

Wx::StaticText nesnesi birçok diğer GUI kütüphanelerinde label adıyla geçen sabit yazı nesnesi, genelde kullanıcının değiştirmeyeceği yazıları bir yerlere yazdırırken kullanırız. 

initialize(parent, id, label, pos = Wx::DEFAULT_POSITION,
  size = Wx::DEFAULT_SIZE, style = 0,
  name = Wx::STATIC_TEXT_NAME_STR)

Bütün temel kontrollerin new metodu benziyor, parent, id, label değerleri sıralı verilmek zorunda diğerleri key parametre olarak verilebilir.

static_text.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    #set_size [350, 250]
    set_title "Orhan Veli Kanık"
    centre

    txt1 = "Eskiler alıyorum
Alıp yıldız yapıyorum
Musiki ruhun gıdasıdır
Musikiye bayılıyorum"

    txt2 = "Şiir yazıyorum
Şiir yazıp eskiler alıyorum
Eskiler verip musikiler alıyorum

Bir de rakı şişesinde balık olsam"

    pnl = Wx::Panel.new self
    vbox = Wx::BoxSizer.new Wx::VERTICAL

    font = Wx::Font.new 13, Wx::FONTFAMILY_DEFAULT,
      Wx::FONTSTYLE_NORMAL, Wx::FONTWEIGHT_NORMAL

    st1 = Wx::StaticText.new pnl, Wx::ID_ANY, txt1, style: Wx::ALIGN_LEFT
    st2 = Wx::StaticText.new pnl, Wx::ID_ANY, txt2, style: Wx::ALIGN_LEFT

    st1.font = font
    st2.font = font

    vbox.add st1, 0, Wx::ALL, 15
    vbox.add st2, 0, Wx::ALL, 15
       
    pnl.set_sizer vbox
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

Ünlü şairimizin çok değerli sözleri.

    font = Wx::Font.new 13, Wx::FONTFAMILY_DEFAULT,
      Wx::FONTSTYLE_NORMAL, Wx::FONTWEIGHT_NORMAL

StaticText nesnelerimizin yazı fontu için kullanacağımız font değerini oluşturuyoruz. 

    st1 = Wx::StaticText.new pnl, Wx::ID_ANY, txt1, style: Wx::ALIGN_LEFT
    st2 = Wx::StaticText.new pnl, Wx::ID_ANY, txt2, style: Wx::ALIGN_LEFT

Şiirimizin iki kıtasını iki StaticText nesnesinde sola hizalanmış olarak yazıyoruz. 

    st1.font = font
    st2.font = font

Yazı fontumuzu , daha önce oluşturduğumuz font yapıyoruz.

    vbox.add st1, 0, Wx::ALL, 15
    vbox.add st2, 0, Wx::ALL, 15

StaticText nesnelerimizi boyutlandırıcıya etraflarında 15 piksel boşluk olacak şekilde ekliyoruz.




Wx::StaticLine

Bu zımbırtı pencerede yatay ya da dikey bir çizgi gösterir. Genelde kontrol gruplarını ayırmak için kullanılır.

initialize(parent, id = Wx::StandardID::ID_ANY, pos = Wx::DEFAULT_POSITION,
  size = Wx::DEFAULT_SIZE, style = Wx::LI_HORIZONTAL,
  name = Wx::STATIC_LINE_NAME_STR)

Sadece parent değeri ile oluştursak default olarak yatay bir çizgi olur. 

static_line.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [360, 380]
    set_title "Wx::StaticLine"
    centre

    pnl = Wx::Panel.new self

    font = Wx::Font.new 10, Wx::FONTFAMILY_DEFAULT,
        Wx::FONTSTYLE_NORMAL, Wx::FONTWEIGHT_BOLD
    heading = Wx::StaticText.new pnl, label: 'Orta Avrupa',
        pos: [25, 15], size: [200, -1]
    heading.font = font

    Wx::StaticLine.new pnl, pos: [25, 50], size: [300,1]

    Wx::StaticText.new pnl, label: 'Slovakya', pos: [25, 80]
    Wx::StaticText.new pnl, label: 'Macaristan', pos: [25, 100]
    Wx::StaticText.new pnl, label: 'Polonya', pos: [25, 120]
    Wx::StaticText.new pnl, label: 'Çek Cumhurüyeti', pos: [25, 140]
    Wx::StaticText.new pnl, label: 'Almanya', pos: [25, 160]
    Wx::StaticText.new pnl, label: 'Slovenya', pos: [25, 180]
    Wx::StaticText.new pnl, label: 'Avusturya', pos: [25, 200]
    Wx::StaticText.new pnl, label: 'İsviçre', pos: [25, 220]

    Wx::StaticText.new pnl, label: '5 445 000', pos: [250, 80]
    Wx::StaticText.new pnl, label: '10 014 000', pos: [250, 100]
    Wx::StaticText.new pnl, label: '38 186 000', pos: [250, 120]
    Wx::StaticText.new pnl, label: '10 562 000', pos: [250, 140]
    Wx::StaticText.new pnl, label: '81 799 000', pos: [250, 160]
    Wx::StaticText.new pnl, label: '2 050 000', pos: [250, 180]
    Wx::StaticText.new pnl, label: '8 414 000', pos: [250, 200]
    Wx::StaticText.new pnl, label: '7 866 000', pos: [250, 220]

    Wx::StaticLine.new pnl, pos: [25, 260], size: [300,1]

    tsum = Wx::StaticText.new pnl, label: '164 336 000', pos: [240, 280]
    sum_font = tsum.get_font
    sum_font.weight = Wx::FONTWEIGHT_BOLD
    tsum.font = sum_font

    btn = Wx::Button.new pnl, label: 'Kapat', pos: [140, 310]

    evt_button(btn) { close }
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

Betiğimiz orta Avrupa ülkeleri ve nüfuslarını gösteriyor. Wx::StaticLine ile görseli yakışıklı yapıyoruz.

    Wx::StaticLine.new pnl, pos: [25, 260], size: [300,1]

300 piksel uzunluğundaki bir çizgiyi yatay olarak yerleştiriyor.




Wx::StaticBox

Bu bir çeşit dekoratör eleman. Değişik elemanları bir grupta toplamak için kullanılır. Bu widget grupladığı widget'lardan önce tanımlanmalıdır, ve o widget'lar StaticBox nesnesinin çocuklarıdır (Wx 2.9.1 öncesi kardeşleri idiler ama şimdi çocukları).

initialize(parent, id, label, pos = Wx::DEFAULT_POSITION,
    size = Wx::DEFAULT_SIZE, style = 0,
    name = Wx::STATIC_BOX_NAME_STR)

Burada label olarak string değer olabileceği gibi, Wx::Window sınıfından üretilmiş bir alt sınıfın nesnesi de olabilir.

static_box.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [270, 250]
    set_title "Wx::StaticBox"
    centre

    pnl = Wx::Panel.new self

    sb = Wx::StaticBox.new pnl, label: 'Kişi Bilgisi', pos: [5, 5], size: [240, 170]
    Wx::CheckBox.new sb, label: 'Erkek', pos: [15, 30]
    Wx::CheckBox.new sb, label: 'Evli', pos: [15, 55]
    Wx::StaticText.new sb, label: 'Yaşı', pos: [15, 95]
    Wx::SpinCtrl.new sb, value: '1', pos: [55, 90], size: [60, -1], min: 1, max: 120

    btn = Wx::Button.new pnl, label: 'Tamam', pos: [90, 185], size: [60, -1]

    evt_button(btn) { close }
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

4 widget'ı saran bir StaticBox kullandık.




Wx::ComboBox

ComboBox bir yazı edit elemanı ve bir liste kutusunun birleşiminden oluşan bir elemandır. Yazı kutusunun yanında bir aşağı ok işareti olur, ona tıklayınca seçenekleri gösteren bir liste açılır. 

initialize(parent, id, value, pos, size, choices, style = 0,
  validator = Wx::DEFAULT_VALIDATOR, name = Wx::COMBO_BOX_NAME_STR)

value içinde o anda yazan değer oluyor. Sadece okunabilir olan elemanlar için ya boş string olmalı ya da seçenek listesinden biri olmalıdır. choices seçeneklerin listesini içeren bir string array. 

combo_box.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [350, 250]
    set_title "Wx::ComboBox"
    centre

    pnl = Wx::Panel.new self

    distros = ['Ubuntu', 'Arch', 'Fedora', 'Debian', 'Mint']
    cb = Wx::ComboBox.new pnl, pos: [50, 30], choices: distros,
            style: Wx::CB_READONLY

    st = Wx::StaticText.new pnl, label: '', pos: [50, 140]
    evt_combobox(cb) { st.label = cb.value }
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

ComboBox'ta seçilen seçenek StaticText üzerinde gösterilecek.

    distros = ['Ubuntu', 'Arch', 'Fedora', 'Debian', 'Mint']

Listedeki seçenekleri bir string array içinde topladık.

    cb = Wx::ComboBox.new pnl, pos: [50, 30], choices: distros,
            style: Wx::CB_READONLY

Wx::CB_READONLY stil bilgisi kutudaki yazının sadece okunabilir olduğunu belirtir. 

    evt_combobox(cb) { st.label = cb.value }

evt_combobox olay işleme metodu listeden bir şey seçince tetiklenir. Önceden seçilmiş olanın aynısını da seçseniz tetiklenir. Sadece combobox okuna ya da combobox dışında bir yere tıklayarak olayı tetiklenmeden çıkabilirsiniz.

value metodu ile ComboBox seçili değeri okuyup StaticText label'ine yazıyoruz.




Wx::CheckBox

CheckBox iki durumu olan bir nesnedir, on ve off. Bir kutu ve yanında bir etiket yazısından oluşur. Etiket kutunun sağında veya solunda olabilir. Eğer CheckBox on durumundaysa kutusunda bit tik işareti olur. Eğer CHK_3STATE stili seçiliyse üçüncü bir durumu olur, bu da genelde seçimin etkisiz olmasını ifade eden anlamlar için kullanılır. 

initialize(parent, id, label, pos = Wx::DEFAULT_POSITION,
  size = Wx::DEFAULT_SIZE, style = 0, validator = Wx::DEFAULT_VALIDATOR,
  name = Wx::CHECK_BOX_NAME_STR)

Olası style değerleri

  • CHK_2STATE : 2 durumlu CheckBox, default budur
  • CHK_3STATE : 3 durumlu CheckBox
  • CHK_ALLOW_3RD_STATE_FOR_USER : Normalde 3 durumlu kullanırken kullanıcı tıklayarak 3. duruma geçiremez, sadece kodla geçirilir. Ama bu stil seçilirse kullanıcı da tıklayarak 3. duruma geçirebilir.
  • Alignment::ALIGN_RIGHT : Etiket yazısı kutunun solunda çıkar, yani kutu sağa hizalanır

check_box.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [350, 250]
    set_title "Wx::CheckBox"
    centre

    pnl = Wx::Panel.new self

    vbox = Wx::BoxSizer.new Wx::VERTICAL

    cb = Wx::CheckBox.new pnl, label: 'Title Göster'
    cb.value = true
    evt_checkbox cb, :show_or_hide_title

    vbox.add cb, 0, Wx::TOP|Wx::LEFT, 30

    cb2 = Wx::CheckBox.new pnl, label: 'Kutu sağda',
      style: Wx::ALIGN_RIGHT
    vbox.add cb2, 0, Wx::TOP|Wx::LEFT, 30

    hbox = Wx::BoxSizer.new Wx::HORIZONTAL
    @cb3 = Wx::CheckBox.new pnl, label: '3 durumlu',
      style: Wx::ALIGN_RIGHT | Wx::CHK_3STATE
    hbox.add @cb3, 0

    @btn1 = Wx::ToggleButton.new pnl, label: "3. durum seç"
    hbox.add @btn1, 0, Wx::LEFT | Wx::RIGHT, 5
    evt_togglebutton(@btn1) { @btn1.value ?
        @cb3.set3state_value(Wx::CHK_UNDETERMINED) :  
        @cb3.set3state_value(Wx::CHK_UNCHECKED) }

    @btn2 = Wx::ToggleButton.new pnl, label: "3. durum serbest"
    hbox.add @btn2, 0
    evt_togglebutton(@btn2) { @btn2.value ?
      @cb3.set_window_style(Wx::ALIGN_RIGHT | Wx::CHK_3STATE |
        Wx::CHK_ALLOW_3RD_STATE_FOR_USER) :  
      @cb3.set_window_style(Wx::ALIGN_RIGHT | Wx::CHK_3STATE) }

    vbox.add hbox, 0, Wx::TOP|Wx::LEFT, 30

    pnl.sizer = vbox
  end
  def show_or_hide_title(e)
    sender = e.get_event_object
    is_checked = sender.value

    if is_checked
      set_title 'Wx::CheckBox'
    else
      set_title ''
    end
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

Bir normal CheckBox, bir kutusu sağda CheckBox ve 3 durumlu bir CheckBox var. 

    cb = Wx::CheckBox.new pnl, label: 'Title Göster'
    cb.value = true

Normal CheckBox tanımı ve başlangıçta tiklenmiş gelmesi. 

    evt_togglebutton(@btn1) { @btn1.value ?
      @cb3.set3state_value(Wx::CHK_UNDETERMINED) :  
      @cb3.set3state_value(Wx::CHK_UNCHECKED) }

Burada önemli bir şey görülüyor. Normal 2 durumlu CheckBox durumu get_value ve set_value (ya da value = ) metodları ile işlenirken, 3 durumlu CheckBox durumları get3state_value ve set3state_value metodları ile işlenir. 3 durumun değerleri ise Wx::CHK_UNCHECKEDWx::CHK_CHECKED ve Wx::CHK_UNDETERMINED - 2 durum olunca sadece true ya da false değer olur. 

    evt_togglebutton(@btn2) { @btn2.value ?
      @cb3.set_window_style(Wx::ALIGN_RIGHT | Wx::CHK_3STATE |
        Wx::CHK_ALLOW_3RD_STATE_FOR_USER) :  
      @cb3.set_window_style(Wx::ALIGN_RIGHT | Wx::CHK_3STATE) }

Wx::CHK_ALLOW_3RD_STATE_FOR_USER stilini ekleyerek kullanıcıya 3. duruma geçirme izni veriliyor, ilk tıklayışta seçili, ikincide tanımsız, üçüncü tıklayışta seçili değil olur. 




Wx::StatusBar

StatusBar (durum çubuğu) elemanı pencerelerin altında bulunan ve kullanıcıyı bilgilendirmek için kullanılan şeride denir. Farklı bilgileri göstermek için bölümlere ayrılabilir. Durum çubuğu içine başka widget'lar da konabilir. Diyaloglarla kullanıcıyı fazla sıkmamak için küçük bilgiler burada verilebilir. Wx::StatusBar iki yöntemle oluşturulabilir: ya kendi StatusBar nesnemizi oluşturup set_status_bar metodu çağırırız, ya da direk create_status_bar metodunu çağırırız. İkinci yöntem bizim için default bir Wx::StatusBar nesnesi oluşturur.

status_bar.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [250, 230]
    set_title "Wx::StatusBar"
    centre

    pnl = Wx::Panel.new self

    button = Wx::Button.new pnl, label: 'Button', pos: [20, 20]
    text = Wx::CheckBox.new pnl, label: 'CheckBox', pos: [20, 90]
    combo = Wx::ComboBox.new pnl, pos: [120, 22], choices: ['Python', 'Ruby']
    slider = Wx::Slider.new pnl, 5, 6, 1, 10, [120, 90], [110, -1]        

    pnl.evt_enter_window { |e| on_widget_enter e }
    button.evt_enter_window { |e| on_widget_enter e }
    text.evt_enter_window { |e| on_widget_enter e }
    combo.evt_enter_window { |e| on_widget_enter e }
    slider.evt_enter_window { |e| on_widget_enter e }

    @sb = create_status_bar
  end
  def on_widget_enter(e)
    isim = e.get_event_object.class.to_s
    @sb.status_text = isim + ' widget'
    e.skip  
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

evt_enter_window ya da buna benzer parametresinde uygulanacağı nesne olmayan olay işleme metodlarda, slider.evt_enter_window şeklinde nesne üzerinde metod çağrılınca sadece blok argüman alıyor. Aslında verdiğimiz metod adını slider nesnesinde arayıp bulamıyor. Bu yüzden blok içinden olay işleyici metoda gönderdik.

    pnl.evt_enter_window { |e| on_widget_enter e }

evt_enter_window olayı widget üzerine mouse girince tetikleniyor. 

  def on_widget_enter(e)
    isim = e.get_event_object.class.to_s
    @sb.status_text = isim + ' widget'
    e.skip  
  end

Önce hangi nesneden olay tetiklendiyse onun sınıf adını alıyoruz. Sonra bu adı durum çubuğuna status_text= metodu ile yazdırıyoruz. set_status_text metodunu da standart Wx metodu olarak kullanabilirdik, ama WxRuby bize kolaylık sağlamış , başka diller gibi set/get uğraşmayalım. Hatta yukarıdaki get_event_object yerine de bunu kullanabiliriz.

  def on_widget_enter(e)
    isim = e.event_object.class.to_s
    @sb.status_text = isim + ' widget'
    e.skip  
  end




Wx::RadioButton

RadioButton kullanıcının bir grup seçenek arasından sadece bir tanesini seçmesini sağlayan widget'dır. Grup belirlemek için grubun ilk RadioButton nesnesine Wx::RB_GROUP stili verilir. Ondan sonra tanımlanan RadioButton nesneleri bu ilk nesne ile aynı grupta kabul edilir. Yeni bir grup başlatmak için, yeni grubun da ilk RadioButton nesnesine Wx::RB_GROUP stili verilir.

radio_button.rb

require "wx"

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [210, 210]
    set_title "Wx::RadioButton"
    centre

    pnl = Wx::Panel.new self

    @rb1 = Wx::RadioButton.new pnl, label: 'Değer A', pos: [10, 10],
            style: Wx::RB_GROUP
    @rb2 = Wx::RadioButton.new pnl, label: 'Değer B', pos: [10, 30]
    @rb3 = Wx::RadioButton.new pnl, label: 'Değer C', pos: [10, 50]
       
    evt_radiobutton @rb1, :set_val  
    evt_radiobutton @rb2, :set_val  
    evt_radiobutton @rb3, :set_val  

    @sb = create_status_bar 3
       
    @sb.set_status_text "true", 0
    @sb.set_status_text "false", 1
    @sb.set_status_text "false", 2
  end
  def set_val(e)
    durum1 = @rb1.value.to_s
    durum2 = @rb2.value.to_s
    durum3 = @rb3.value.to_s

    @sb.set_status_text durum1, 0
    @sb.set_status_text durum2, 1
    @sb.set_status_text durum3, 2      
  end
end

Wx::App.run {
  Örnek.new(nil).show
}


3 tane RadioButton nesnemiz var.

    @rb1 = Wx::RadioButton.new pnl, label: 'Değer A', pos: [10, 10],
            style: Wx::RB_GROUP
    @rb2 = Wx::RadioButton.new pnl, label: 'Değer B', pos: [10, 30]
    @rb3 = Wx::RadioButton.new pnl, label: 'Değer C', pos: [10, 50]

İlkinin stiline Wx::RB_GROUP değeri verdik. Daha sonra gelenler aynı grubta kabul edilir. 

    evt_radiobutton @rb1, :set_val  

@rb1 seçilince set_val metodu çağrılıyor.

    @sb = create_status_bar 3
       
    @sb.set_status_text "true", 0

3 bölmeli bir StatusBar tanımlıyoruz. set_status_text  metodu ilk argümanda yazılacak yazıyı, ikinci argümanda hangi bölmeye yazılacağını alıyor. 

    durum1 = @rb1.value.to_s

RadioButton değeri true ya da false olacaktır. 




Wx::Gauge

Wx::Gauge uzun süren işlemlerimizde kullanıcıyı işlemin ne kadarının gerçekleştiği konusunda bilgilendirmek için kullandığımız bir widget. 

gauge_wid.rb

require "wx"

GÖREV_ORANI = 50

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [350, 210]
    set_title "Wx::Gauge"
    centre

    @timer = Wx::Timer.new self
    @count = 0

    evt_timer @timer, :on_timer

    pnl = Wx::Panel.new self

    vbox = Wx::BoxSizer.new Wx::VERTICAL
    hbox1 = Wx::BoxSizer.new Wx::HORIZONTAL
    hbox2 = Wx::BoxSizer.new Wx::HORIZONTAL
    hbox3 = Wx::BoxSizer.new Wx::HORIZONTAL

    @gauge = Wx::Gauge.new pnl, range: GÖREV_ORANI, size: [250, -1]
    btn1 = Wx::Button.new pnl, Wx::ID_OK
    btn2 = Wx::Button.new pnl, Wx::ID_STOP
    @text = Wx::StaticText.new pnl, label: 'Görev Başlayacak'

    evt_button btn1, :on_ok
    evt_button btn2, :on_stop

    hbox1.add @gauge, Wx::ALIGN_CENTRE
    hbox2.add btn1, Wx::RIGHT, 10
    hbox2.add btn2
    hbox3.add @text

    vbox.add 0, 30  # boşluk ekleme

    vbox.add hbox1, 1, Wx::ALIGN_CENTRE

    vbox.add 0, 20

    vbox.add hbox2, 1, Wx::ALIGN_CENTRE
    vbox.add hbox3, 1, Wx::ALIGN_CENTRE

    pnl.sizer = vbox
  end
  def on_ok(e)
    if @count >= GÖREV_ORANI
      return
    end

    @timer.start 100
    @text.label = 'Görev Çalışıyor'  
  end
  def on_stop(e)
    if @count == 0 or @count >= GÖREV_ORANI or not @timer.is_running
      return
    end

    @timer.stop
    @text.label = 'Görev Durduruldu'
  end
  def on_timer(e)
    @count += 1
    @gauge.value = @count

    if @count == GÖREV_ORANI
      @timer.stop
      @text.label = 'Görev Tamamlandı'
    end
  end
end

Wx::App.run {
  Örnek.new(nil).show
}


Bir tane Gauge ve iki butonumuz var. Bir buton görevi başlatıyor, diğer, olduğu yerde durduruyor.

    @timer = Wx::Timer.new self
    @count = 0

Görev ilerliyormuş gibi göstermek için bir timer yardımıyla @count değerini zamanla arttıracağız. @count değişkenindeki değer sanki görevin o kadarı gerçekleşmiş gibi Gauge'de gösterilecek. 

    @gauge = Wx::Gauge.new pnl, range: GÖREV_ORANI, size: [250, -1]

Wx::Gauge nesnesi oluşturma kodu, range key parametresi hangi değerde %100 görüneceğini belirler.

  def on_ok(e)
    if @count >= GÖREV_ORANI
      return
    end

    @timer.start 100
    @text.label = 'Görev Çalışıyor'  
  end

OK butonuna tıklanınca eğer sayaç hala maksimum değerimize gelmediyse zamanlayıcıyı 100ms aralıkla çalıştırıyoruz, ve yazıya da görevin çalışıyor olduğunu yazdırıyoruz.

  def on_stop(e)
    if @count == 0 or @count >= GÖREV_ORANI or not @timer.is_running
      return
    end

    @timer.stop
    @text.label = 'Görev Durduruldu'
  end

Stop butonu tıklanınca eğer görev devam ediyorsa zamanlayıcı çalışmasını durdurup sayacın olduğu değerde kalmasını sağlıyoruz. 

  def on_timer(e)
    @count += 1
    @gauge.value = @count

    if @count == GÖREV_ORANI
      @timer.stop
      @text.label = 'Görev Tamamlandı'
    end
  end

Zamanlayıcı çalıştığı müddetçe on_timer olay işleme metodu periyodik olarak çağrılır. Sayaç değeri arttırılır, ve eğer maksimum değere ulaştıysa zamanlayıcı durdurulur.




Wx::Slider

Bu bir sürgü gibi tutup sağa sola çekerek bir değeri değiştirmek için kullandığımız eleman. 

slider_wid.rb

require "wx"

GÖREV_ORANI = 50

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    set_size [350, 210]
    set_title "Wx::Slider"
    centre

    pnl = Wx::Panel.new self
    sizer = Wx::GridBagSizer.new 5, 5

    sld = Wx::Slider.new pnl, value: 200, min_value: 150, max_value: 500,
                        style: Wx::SL_HORIZONTAL

    sld.evt_scroll { |e| on_slider_scroll e }
    sizer.add sld, Wx::GBPosition.new(0,0), Wx::DEFAULT_SPAN,
Wx::ALL | Wx::EXPAND, 25

    @txt = Wx::StaticText.new pnl, label: '200'
    sizer.add @txt, Wx::GBPosition.new(0,1), Wx::DEFAULT_SPAN,
Wx::TOP | Wx::RIGHT, 25

    sizer.add_growable_col 0
    pnl.sizer = sizer
  end
  def on_slider_scroll(e)
    obj = e.event_object
    val = obj.value

    @txt.label = val.to_s
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

Slider sürgüsünü kaydırarak elde edilen değer yazdırılıyor. 

    sld = Wx::Slider.new pnl, value: 200, min_value: 150,
            max_value: 500, style: Wx::SL_HORIZONTAL

Slider üretim kodu. value , o anki değer. min_value ve max_value alt ve üst sınırlar. 

    sld.evt_scroll { |e| on_slider_scroll e }

Scroll olayı slider sürgüsü kaydırılınca oluşur.

  def on_slider_scroll(e)
    obj = e.event_object
    val = obj.value

    @txt.label = val.to_s
  end

Slider value değerini yazdırır, hani yukarının yerine direk

    sld.evt_scroll { @txt.label = sld.value.to_s }

Yazsak da olurdu ama örneğimiz biraz da daha çaplı bir olay işleme gerekince nasıl yapılanılacağını göstermek için.




Wx::SpinCtrl

Wx::SpinCtrl elemanı bir değeri arttırıp eksiltmek amacıyla kullandığımız elemandır. 

spin_ctrl.rb

require "wx"
require "./my_wx_helper"

GÖREV_ORANI = 50

class Örnek < Wx::Frame
  def initialize(*args)
    super(*args)
    init_UI
  end
  def init_UI
    #set_size [350, 210]
    set_title "Wx::SpinCtrl"
    centre

    pnl = Wx::Panel.new self
    sizer = Wx::GridBagSizer.new 5, 5

    st1 = Wx::StaticText.new pnl, label: "Fahrenheit sıcaklığı Celsius'a dönüştürün"
    sizer.add st1, [0, 0], [1, 2], Wx::ALL, 15

    st2 = Wx::StaticText.new pnl, label: 'Fahrenheit:'
    sizer.add st2, [1, 0], Wx::DEFAULT_SPAN, Wx::ALL | Wx::ALIGN_CENTER, 15
       
    @sc = Wx::SpinCtrl.new pnl, value: '0'
    @sc.set_range(-459, 1000)

    sizer.add @sc, [1, 1], [0, 0], Wx::ALIGN_CENTER

    st3 = Wx::StaticText.new pnl, label: 'Celsius:'
    sizer.add st3, [2, 0], [0, 0], Wx::ALL|Wx::ALIGN_RIGHT, 15

    @celsius = Wx::StaticText.new pnl, label:''
    sizer.add @celsius, [2, 1], [0, 0], Wx::ALL, 15

    compute_button = Wx::Button.new pnl, label: 'Hesapla'
    compute_button.set_focus
    sizer.add compute_button, [3, 0], [0, 0], Wx::ALIGN_RIGHT|Wx::TOP, 30

    close_button = Wx::Button.new pnl, label: 'Kapat'
    sizer.add close_button, [3, 1], [0, 0], Wx::ALIGN_LEFT|Wx::TOP, 30

    evt_button compute_button, :on_compute
    evt_button(close_button) { close }

    pnl.sizer = sizer
  end
  def on_compute(e)
    fahr = @sc.value
    cels = (fahr - 32) * 5 / 9.0
    @celsius.label = cels.round(2).to_s
  end
end

Wx::App.run {
  Örnek.new(nil).show
}

Burada GridBagSizer boyutlandırıcısı add metodunu değiştiren bir helper dosyam var, daha önce bahsetmiştim.

my_wx_helper.rb

class Wx::GridBagSizer
  wx_add = instance_method :add
  wx_redefine_method :add do |*args|
    if args[1].class == Array && args[1].length == 2
      args[1] = Wx::GBPosition.new args[1][0], args[1][1]
    end
    if args[2].class == Array && args[2].length == 2
      args[2] = Wx::GBSpan.new args[2][0], args[2][1]
    end
    wx_add.bind(self).call(*args)
  end
end

Bu sayede pos ve span değerlerini daha basit girebiliyorum. 

    @sc = Wx::SpinCtrl.new pnl, value: '0'
    @sc.set_range(-459, 1000)

Spin kontrolümüzü bir başlangıç değeriyle oluşturuyoruz, alt ve üst sınırlarını set_range ile veriyoruz. 

Spin kontrolü bir özelliği de direk kutu içine sayı da yazabiliriz, ille yukarı-aşağı butonlarını kullanmak zorunda değiliz. set_increment metodu ile (veya increment= ) her tıklayıştaki artış miktarını belirleriz. 



Temel widget'lar bunlar. Sonraki bölümde gelişmiş widget'lar ile devam edeceğiz inşallah, şimdilik kalın sağlıcakla..







Hiç yorum yok:

Yorum Gönder