0

Javafx Properties & Bindings Part-2

Javafx Properties & Bindings yazısının ikinci bölümünden devam edelim. Birinci bölümü okumadan bu bölüme geçmenizi tavsiye etmem eğer okumadıysanız part-1 kısmını mutlaka okuyun.

JAVAFX  JavaBean

Yazının üst kısımlarında Java Bean düzeninden bahsetmiştik şimdi javafx javaBean dan bahsedelim ve nasıl alanlar oluşturulur buna bakalım.Bu örneğimizde readOnly bir property kullanacağız ta ki readOnly property’nin davranışlarını görmüş olalım.

package com.company;

import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class User {

    private  final static String USERNAME_PROP_NAME="userName";
    private final ReadOnlyStringWrapper userName;
    private final static String PASSWORD_PROP_NAME="password";
    private final StringProperty password;
    private final ReadOnlyStringProperty userNameReadOnlyProperty;
    
    
    public User() {

        this.userName = new ReadOnlyStringWrapper(this,USERNAME_PROP_NAME,System.getProperty("user.name"));
        userNameReadOnlyProperty =userName.getReadOnlyProperty();
        this.password=new SimpleStringProperty(this,PASSWORD_PROP_NAME,"");

    }

    // StringProperty türünde password  read /write 
    public String getPassword() {
        return password.get();
    }

    public StringProperty passwordProperty() {
        return password;
    }

    public void setPassword(String password) {
        this.password.set(password);
    }


    // userNameReadOnlyProperty için ReadOnlyStringProperty türünde idi.
    // dikkat edelim set metodu yok

    public String getUserNameReadOnlyProperty() {
        return userNameReadOnlyProperty.get();
    }

    public ReadOnlyStringProperty userNameReadOnlyPropertyProperty() {
        return userNameReadOnlyProperty;
    }

   

    // ReadOnlyStringwrapper nesnesinden türetilen UserName için  arka planda read/write idi
    // dikkat edelim set metodu var
    
    public String getUserName() {
        return userName.get();
    }

    public ReadOnlyStringWrapper userNameProperty() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName.set(userName);
    }
}

örneğimize dikkat edersek ReadOnlyStringWrapper ‘in read/write özellikli olduğunu , ReadOnlyStringProperty ise set metodu olmadığını görürür. açıklamalara kod arasına yazdım. 

Constructorda şu şekilde tanınmalama yapılmasının sebebi olarak ; 

userName = new ReadOnlyStringWrapper(this, USERNAME_PROP_NAME, System.getProperty("user.name"));
password = new SimpleStringProperty(this, PASSWORD_PROP_NAME, "");

property’lere change listener eklerken bean nesnesine erişim gerekebiliyor o yüzden bu şekilde constructor tanımlanmış.

Property  Change Desteği

Property’lerin change desteginin olması property de herhangi bir değişiklik meydana geldiğinde bu değişikliği yakalamayı sağlıyor. Aynen butona basma olayının yakalanması gibi.. Javafx Objelerinin addListener() diye bir metodu var. Bu metod iki tane Functional Interface ‘i parametre olarak alabiliyor. Bunlar ChangeListener ve Invalidationlistener. Dolayısıyla bunları lambda Expression ile kullanabiliyorsunuz anlamına da geliyor. 

Javafx deki tüm property’lerin dedeleri ObservableValue ve Observable interfacesidir. 

resimleri incelerseniz bunların addListener() diye bir metodu var ve bu metodlar ChangeListener , ve InvalidationListener diye iki parametrede alıyor. Tabi burada removeListener() da ilgilimiz çekiyor. Oluşturduğumuz listener’larla işimiz bitince bunları hafızadan temizlemek de önemli bir nokta , removeListener ile bu listener’ları kaldırabiliyoruz. 

Şimdi kodumuzun içinde bu durumu nasıl örnekleriz buna bakalım . Örneğimizde read/writable bir StringProperty Oluşturacağız ve bu proprety’ e hem anonim inner class olarak, hemde lambda kullanarak bir change listener ekleyeceğiz. 

        SimpleStringProperty xProperty=new SimpleStringProperty();

        // Anonim inner Class olarak change listener ekleyelim
        
        
        xProperty.addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                // xProperty değeri değiştiğinde olacak işleri buraya yazacağız
                
            }
        });

        xProperty.addListener((observable, oldValue, newValue) -> {
            // Lambda ile olan versiyonu
            // xProperty değeri değiştiğinde olacak işleri buraya yazacağız
            
        });

Şimdi de InvalidationListener nasıl oluşturulur buna bakalım. Property’mizin değeri değiştiğinde invalidated() metodu tetiklenecek. Hem lambda hemde anonim inner class olarak örneğimizi yapacağız. 

   SimpleStringProperty xProperty=new SimpleStringProperty();

        // Anonim inner Class olarak change listener ekleyelim

        xProperty.addListener(new InvalidationListener() {
            @Override
            public void invalidated(Observable observable) {
                // xProperty değeri değiştiğinde çalışacak kodlan
            }
        });
        
        // Lambda ile yazılan versiyonu
        
        xProperty.addListener(observable -> {
            
            // xProperty değeri değiştiğinde çalışacak kodlan
        });

Genellikle yazılımcılar bu ikisi yani changeListener ve invalidationListener arasındaki fark ne diye düşünüyorlar. ChangeListener kullanıldığında elimizde ObservableValue , oldValue ve newValue diye 3 tane nesnemiz oluyor. Ancak InvalidationListener da sadece bir Observable nesnesi dönüyor. Bu durumda oldvalue ve newValue değerleri hesaplanmadığından bir performans olarak size yansıyor. Yani grafiksel bir işlem yaptığınızı düşünün burada kullanırken gereksiz yere yapılan işler bilgisayarda performans kaybına neden olacaktır. eski ve yeni değerlerin değerlendirmeye alınmadığı durumlarda kullanılabilir. Örnek basit bir uygulama ekleyelim.

package sample;

import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.util.Scanner;

public class Main  {




    public static void main(String[] args) {

        Counter counter=new Counter();
        counter.counterProperty().addListener((observable, oldValue, newValue) -> {

            System.out.println("Önceki counter değeri: "+oldValue +" Şimdiki değer: "+newValue);
        });
        Scanner scanner=new Scanner(System.in);
        while (true){

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            counter.setCounter(counter.getCounter()+1);
        }

    }
}

class Counter{
    SimpleIntegerProperty counter=new SimpleIntegerProperty(0) ;

    public int getCounter() {
        return counter.get();
    }

    public SimpleIntegerProperty counterProperty() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter.set(counter);
    }
}

Ekran Çıktısı: 
Önceki counter değeri: 0 Şimdiki değer: 1
Önceki counter değeri: 1 Şimdiki değer: 2
Önceki counter değeri: 2 Şimdiki değer: 3
Önceki counter değeri: 3 Şimdiki değer: 4
Önceki counter değeri: 4 Şimdiki değer: 5

şeklinde devam edecektir. 

admin

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir