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