Oca
30
2012

Vaadin’de Component’ler, Formlar ve Event-Listener Mekanizması

Geçen makalemde Vaadin için ilk projemizi oluşturmuş ve uygulama sınıfımız içinde bir Window oluşturarak içine “Merhaba Kodcu.Com” yazdırmıştık.

Şimdi ise detaya inerek Vaadin component’lerini ve bu componentlere(örn. bir butona) event ve listener mekanizmaları ile nasıl iş yaptırabileceğimizi görelim.

Vaadin componentleri şunlardır:

*Label: Etiket componentidir. Ekrana etiket(yazı) ekler.

*Link: Bilindik link oluşturur.

*TextField: Bir textbox’ı ifade eder.

*TextArea: Bir texarea’yı ifade eder.

*PasswordField: Şifre girişi için kullanılan textbox’tır.

*RichTextArea: Yazıyı zengin biçimde değiştirebileceğiniz, bold vb. biçimlendirebileceğiniz bir componenttir. TextArea’nın gelişmişi olarak düşünebilirsiniz. Mail gönderirken içerik yazdığımız kısma benzer.

*PopupDateField: Tarih alanı için takvimli bir component’i ifade eder.

*InlineDateField: Takvim objesini form içine direk yerleştirerek bir date picker sağlar.

*Button: Buton’dur.

*CheckBox: Bildiğimiz seçim kutusunu ifade eder. Ancak bu component bir checkbox grubu oluşturmaz.

*Select: Tek seçimli modta bilindik drop-down listesini ifade eder. Çok seçimli modta ise ListSelect componenti gibi çalışır. Kullanıcı Textbox alanına yazı girerek filtreleme yapabilir.

*ComboBox: Select’in tek seçimli hali gibidir, ancak bu componente kullanıcı yeni item’lar ekleyebilir.

*ListSelect: Tek ve çok seçimli modları vardır. Filtreleme ya da yeni item ekleme yoktur.

*NativeSelect: HTML’deki <select> elementini kullanır, ve işletim sistemi temasını taşır.

*OptionGroup: Tek seçimli(option grubu), ve çok seçimli(checkbox grubu) olmak üzere iki modu vardır.

*TwinColSelect: Soldan sağa item taşınıp geri alınabilecek şekilde sağ ve solda iki listbox’ın bulunduğu bir componenttir.

*Table: Tablo oluşturur. Sorting ve paging eklenebilir, filtreleme yapılabilir, içindeki veriler editlenebilir yapılabilir.

*Tree: Hiyerarşik görünümde itemları listeler. Sol menülerde kullanılabilir.

*MenuBar: Yatay bir menü oluşturur. Altına MenuItem’lar eklenerek zengin menüler oluşturulabilir. Her MenuItem’a bir Command bağlanarak istenilen iş yaptırılabilir.

*Embedded: Embedded nesnesi aldığı tip state’ine göre image,flash object, iframe görevi görebilecek bir nesnedir.

*Upload: Upload nesnesi upload’un tüm kontrollerini yapmaya yarayan, upload başlangıcı, bitişi, süresince yapılacak işleri belirtmeye kolaylık sağlayan bir component’tir.

*ProgressIndicator: Genelde Upload component’i ile birlikte kullanılan süreç gösterim çubuğudur.

*Slider: Yatay ya da dikey olarak kaydırma çubuğu componenti’dir.

*LoginForm componenti’dir. Bir username ve password alanını barındırır.

Son olarak ve en önemlisi:

*Form: Tüm web geliştirme dünyasındaki form elementini ifade eder. Html <form> nesnesi oluşturur. Vaadinde Form nesnesi ile <form> elementini yönetebiliriz.

Şimdi çalışmamıza başlayalım.

Önceki dersi uygulayıp bir proje oluşturduysanız mevcut proje üzerinden, değilse yeni bir Vaadin projesi oluşturalım. Ben daha net olması açısından yeni bir proje oluşturacağım ve bu projeye “VaadinFormCalismasi” adını verecegim. Siz dilerseniz başka bir isim verebilirsiniz. İşte oluşturduğum projenin ve Eclipse Vaadin plug-in’i sayesinde otomatik oluşan Application sınıfımızın görüntüsü:

Geçen dersten de hatırladığınız üzere herşey uygulama sınıfımız içindeki init() metodunda bitiyordu. Bu sınıf proje oluşurken otomatik oluştuğundan init() içeriği de otomatik olarak oluşmakta, o yüzden init() metodu içeriğini silerek işe başlayalım:

Şimdi init() içeriğini sildiğimize göre sıfırdan başlayarak bir uygulama geliştirebiliriz. Biliyorsunuz ki uygulamanın her birimi Window nesneleri üzerinden yayınlandığından bir Window objesi oluşturmamız gerekiyor. Bir Window objesi oluşturalım ve uygulamamızın ana penceresini oluşturduğumuz Window objesi olarak gösterelim. Bunun için hatırlayacağınız gibi setMainWindow() metodunu kullanmamız gerekiyordu:

public void init() {
Window formPenceresi = new Window("Kodcu.Com Vaadin Form Penceresi");
setMainWindow(formPenceresi);
}

Buraya kadar her şey çok güzel. Yeni bir pencere oluşturduk ve bunu uygulamamızda ana penceremiz yaptık. İşte şimdi farklı birşey geliyor: Form objesi. Web uygulamalarına aşina olanlar bilirler; form objesi veri post ya da get işlemlerini server tarafa yapmamızı sağlayan yapıyı ihtiva eder. Kullanıcı girmesi gereken bilgileri formdaki alanlara girerek ve formu submit ederek bu bilgilkerin kullanılacağı ya da kaydedileceği yerlere gönderir. JSF, JSP, PHP vb. klasik web uygulamalarında form elementi oldukça sık kullanılır.Bu teknolojilerde Form’un kullanılmayılıp, bu işi Ajax post-get olarak yapmak da mümkündür ancak bu teknolojiler yapısal olarak form kullanımını destekler ve buna oldukça müsaittirler.

Ancak Vaadin’de işler biraz karışık diyebiliriz. Vaadin yapı itibariyle bir web uygulama çatısından çok bir masaüstü uygulama çatısına benzediğinden Form objesi kullanımı için programcıyı zorlamamaktadır. İşini kendi Ajax yapısı ile de kotarabilmektedir dolayısıyla Form objesi ile yapılabilecek şeyler kullanmadan da yapılabilir. Ancak özellikle form validasyonu ve form temizleme gibi konularda programcıya ekstra yük bindirdiği, ve her ne kadar bir GUI geliştirme uygulama çatısına benzese de halihazırda bir web uygulama çatısı olduğundan, ve form yapısı ile birlikte bir de bean-form binding özelliği de getirdiğinden(bundan sonra bahsedeceğiz) ben Vaadin’de form kullanımını kesinlikle desteklemekte ve önermekteyim. Bu GUI programlama’dan web programlamaya geçmiş ve “Vaadin ile başlayayım, nasılsa desktop programlamaya yakın” diyen arkadaşlar için biraz zor olabilir ancak şunu da tekrar belirtmek gerekir ki formlar web’in olmazsa olmazıdır.

Bu kadar kıssa’dan hissemizi kopararak devam edelim ve formumuzu ekleyelim:

public void init() {
Window formPenceresi = new Window("Kodcu.Com Vaadin Form Penceresi");
setMainWindow(formPenceresi);

Form formum = new Form();
formum.setCaption("Bilgi Formu");
}

Gördüğünüz üzere Form formum = new Form(); diyerek form objesini oluşturduk, ardından da setCaption metodu ile formumuza bir caption verdik(Caption zorunlu değildir). Peki “formum” isimli form bu şekliyle sizce görüntülenebilir mi? Tabi ki hayır. Çünkü formu henüz Window nesnemiz olan “formPenceresi” içine koymadık. Formu penceremiz içine koyalım:

public void init() {
Window formPenceresi = new Window("Kodcu.Com Vaadin Form Penceresi");
setMainWindow(formPenceresi);

Form formum = new Form();
formum.setCaption("Bilgi Formu");
formPenceresi.addComponent(formum);
}

Şimdi ise forma yukarıda bahsettiğimiz componentlerden kullanım amacımıza göre ekleyeceğiz. Ben forma “Bilgi Formu” adını verdiğim için Adı, Soyadı ve Açıklama alanlarını ekleyip bir de “Gönder” ismiyle bir buton koyacağım. Önce componentlerimizi oluşturalım:

public void init() {
Window formPenceresi = new Window("Kodcu.Com Vaadin Form Penceresi");
setMainWindow(formPenceresi);

Form formum = new Form();
formum.setCaption("Bilgi Formu");
formPenceresi.addComponent(formum);

TextField txtAdi = new TextField("Adı");
TextField txtSoyadi = new TextField("Soyadı");
TextArea txtAciklama = new TextArea("Açıklama");
Button btnGonder = new Button("Gönder");
}

Componentlerimizi oluşturduk. Ancak bu componentler ne window içine ne de form içine eklenmediğinden görüntülenemeyecektir. Dolayısıyla ya Window objemiz içine ya da formumuz içine addComponent() metodu ile eklememiz gerekiyor. Eğer yukarıda bahsettiğim gibi form objesi kullanmadan geliştirme yapacaksak direk formPenceresi içine componentlerimizi eklemek yerinde olurdu ancak biz halihazırda formumuzu penceremiz içine eklediğimizden ve form kullanmak durumunda olduğumuzdan componentlerimizi form içine ekleyeceğiz. Ve bunun için yine addComponent() metodunu kullanacağız:

O da ne! form obje referansımız olan “formum” üstünde bir addComponent() metodu yok diyor. Demek ki form objemiz üzerine direk component ekleyemiyoruz. Biraz araştırınca öğreniyoruz ki Vaadin geliştiricisi arkadaşlar form component’lerinin layout’lar üzerinden eklenmesine izin vermişler. Normalde bir formu üzerine setLayout() diyerek bir layout tanımlayabiliyoruz, ancak bu konu şu an için konumuz dışında.Biz bu makalede Form objelerinin default layout’u ne ise onun üzerinden gideceğiz(Default’u artık deprecate olup yerini Vertical ve Horizontal layouta bırakan Orderedlayout’tan türeyen FormLayout’tur).

Form üzerinde getLayout() diyerek default layoutumuzu aldıktan sonra artık addComponent() diyebilir, componentlerimizi ekleyebiliriz:

public void init() {
Window formPenceresi = new Window("Kodcu.Com Vaadin Form Penceresi");
setMainWindow(formPenceresi);

Form formum = new Form();
formum.setCaption("Bilgi Formu");
formPenceresi.addComponent(formum);

TextField txtAdi = new TextField("Adı");
TextField txtSoyadi = new TextField("Soyadı");
TextArea txtAciklama = new TextArea("Açıklama");
Button btnGonder = new Button("Gönder");

formum.getLayout().addComponent(txtAdi);
formum.getLayout().addComponent(txtSoyadi);
formum.getLayout().addComponent(txtAciklama);
formum.getLayout().addComponent(btnGonder);
}

Uygulamamızı bu haliyle çalıştıralım:

Gördüğünüz gibi Ad, Soyad, Açıklama alanlarımız ve “Gönder” butonumuz geldi. Bilgileri doldurup “Gönder”‘e bastığımızda butonun herhangi bir şey yapmadığını siz de farkettiniz mi? Bunun sebebi ona yapılacak bir iş vermememizdir.

Size daha önceki makalemde Vaadin’in olay güdümlü bir uygulama çatısı olduğundan bahsetmiştim. Vaadin’de component’lere yapacağı iş event-listener mekanizmaları ile sağlanır. Swing’te olduğu gibi her listener bir anonymous-class(detaylı bilgi için Altuğ Bey’in kitabından yararlanabilirsiniz)’tır ve override edilmesi gereken bir metodu ve bu metoda verilen bir “event” parametresi vardır. Şimdi isterseniz detaydan biraz uzaklaşıp, butonumuza bir event listener ekleyelim. Ancak eklemeden önce butonun addListener() metodunun hangi listener parametrelerini aldığına bir göz atalım:

Biz bu liste içinden ClickListener’ tipinde bir listener ekleyeceğiz. Buna bağlı olarak override edilmesi gereken metod tabii ki değişecek. Biraz Eclipse Ctrl+SpaceBar sihrinden de yararlanarak ClickListener’ımızı ekliyoruz:

public void init() {
Window formPenceresi = new Window("Kodcu.Com Vaadin Form Penceresi");
setMainWindow(formPenceresi);

Form formum = new Form();
formum.setCaption("Bilgi Formu");
formPenceresi.addComponent(formum);

TextField txtAdi = new TextField("Adı");
TextField txtSoyadi = new TextField("Soyadı");
TextArea txtAciklama = new TextArea("Açıklama");
Button btnGonder = new Button("Gönder");
btnGonder.addListener(new ClickListener() {

public void buttonClick(ClickEvent event) {
// TODO Yapılacak iş buraya eklenecek

}
});

formum.getLayout().addComponent(txtAdi);
formum.getLayout().addComponent(txtSoyadi);
formum.getLayout().addComponent(txtAciklama);
formum.getLayout().addComponent(btnGonder);
}

Yukarıdaki kodta TODO task olarak belirttiğim “Yapılacak iş buraya eklenecek” ibaresinin olduğu yere dikkat ediniz. Burası anonymous classımız olan ClickListener’ın(aslında bir interface’tir ve dolayısıyla metodunu override etmeye zorunlu kılar) overrided buttonClick() metodu içidir. Burada yapılan olay ne ise o yakalanır ve “event” obje referansı üzerinde tutulur.

Bizim amacımız formu bir yere submit etmek, yani göndermek olduğundan buttonClick() metodumuz içine formu submit edeceğimiz kodu yazmalıyız. Ancak bilinmelidir ki Vaadin’de aslında formu submit etmek diye birşey yoktur. Yaratılan obje değeri serverda yaşar ve istenildiği zaman kullanılabilir. O sebeple de formum.submit() gibi bir metod değil de direk işimizi yapacak kodu kendimiz yazmalıyız. Bunun için projeye doldurulan form bilgilerini göndereceğimiz bir sayfa eklememiz gerekiyor. Bunu plug-in vasıtasıyla “Vaadin Composite” ekleyerek yapacağız.

Projeye sağ tıklayıp New>Others’ı seçelim ve Vaadin grubu altından “Vaadin Composite”‘i seçip “Next” diyelim.

Paket ve sınıf adını belirledikten sonra “Finish” diyerek sınıfımızı ekleyelim. Ben Paket adı sabit kalacak şekilde Composite sınıfıma “VaadinComposite” adını veriyorum:

Oluşturduğumuz VaadinComposite sınıfının yapısı şöyledir:

package com.example.vaadinformcalismasi;

import com.vaadin.annotations.AutoGenerated;
import com.vaadin.ui.AbsoluteLayout;
import com.vaadin.ui.CustomComponent;

public class VaadinComposite extends CustomComponent {

private AbsoluteLayout mainLayout;

public VaadinComposite() {
buildMainLayout();
setCompositionRoot(mainLayout);
}

private void buildMainLayout() {
mainLayout = new AbsoluteLayout();
}
}

VaadinComposite sınıfı bir componenttir ve CustomComponent’ten türemiştir. Yani bu demek oluyor ki biz VaadinComposite componentimizi bir window’un içine koyabiliriz. Burada ana layout objemiz olan mainLayout referansımızı, sınıf constructor’ımızı ve constructor icinde cağırılan buildMainLayout() ve setCompositionRoot() isimli metodları görüyoruz. buildMainLayout() metodu mainLayout’un tanımlandığı ve componentlerimizi tanımlayıp bu layout içine eklememiz gereken yer iken, constructor içindeki setCompositionRoot ise componentin root’unun hangi layout olduğunu belirtir. (Not: Sizin projenizde bazı field’lar ya da metodlar üzerinde @Autogenerated isimli bir annotation görebilirsiniz. Bu durum kafanızı karıştırmasın, çünkü bu annotation’ları sadece Vaadin’in form designer’ı kullanıyor. Ben bu sebeple işimize yaramayacağından ötürü bu örnekte kaldırdım.)

mainLayout’ tipinin AbsoluteLayout olduğunu farketmişsinizdir. Bu Vaadin’in form designer’ını kullananlar için bir avantajdır(component istenilen düzende yerleştirilebilir) ancak bir uygulamamızı kod bazlı yazdığımızdan VerticalLayout ya da HorizontalLayout alternatiflerinden birini kullanacağız.

Formun yapısındaki gibi form submit edildikten sonra gösterilen formda da bilgileri alt alta görmek isteyeceğimizden VerticalLayout kullanacağız. Bu sebeple de mainLayout tipini AbsoluteLayout’tan VerticalLayout’a çevirelim:

public class VaadinComposite extends CustomComponent {

//VerticalLayout olarak değiştirdik
private VerticalLayout mainLayout;

public VaadinComposite() {
buildMainLayout();
setCompositionRoot(mainLayout);
}

private void buildMainLayout() {
mainLayout = new VerticalLayout();
}
}

Şimdi yapmamız gereken şey ise Composite sınıfımızda formdaki her alana karşılık gelecek Label’ları mainLayout’umuz içine eklemek oluyor:

private void buildMainLayout() {
// the main layout and components will be created here
mainLayout = new VerticalLayout();

Label lblAdi = new Label();
Label lblSoyadi = new Label();
Label lblAciklama = new Label();

mainLayout.addComponent(lblAdi);
mainLayout.addComponent(lblSoyadi);
mainLayout.addComponent(lblAciklama);
}

Label’larımızı mainLayout içine ekledik. Artık VaadinComposite componentimiz nereye eklenirse eklensin Label’larımız görünecektir. Ancak şu durumda gözükmez çünkü en önemli şeyi, yani Label’lara birer caption eklemeyi unuttuk. Label’ların her biri formdan gelen veriyi göstereceği için yapıyı dinamik kurmamız gerekecektir. Bunun için ise VaadinComposite classı içinde label alanlarımızı private field’lara çevirelim ve getter/setterlar’ını oluşturalım(referansları private tanımladığımızdan bunu yapmak durumundayız).

public class VaadinComposite extends CustomComponent {

// VerticalLayout olarak değiştirdik
private VerticalLayout mainLayout;

private Label lblAdi;
private Label lblSoyadi;
private Label lblAciklama;

public VaadinComposite() {
buildMainLayout();
setCompositionRoot(mainLayout);
}

private void buildMainLayout() {
mainLayout = new VerticalLayout();

lblAdi = new Label();
lblSoyadi = new Label();
lblAciklama = new Label();

lblAdi.setImmediate(true);
lblSoyadi.setImmediate(true);
lblAciklama.setImmediate(true);

mainLayout.addComponent(lblAdi);
mainLayout.addComponent(lblSoyadi);
mainLayout.addComponent(lblAciklama);
}

public Label getLblAdi() {
return lblAdi;
}

public void setLblAdi(Label lblAdi) {
this.lblAdi = lblAdi;
}

public Label getLblSoyadi() {
return lblSoyadi;
}

public void setLblSoyadi(Label lblSoyadi) {
this.lblSoyadi = lblSoyadi;
}

public Label getLblAciklama() {
return lblAciklama;
}

public void setLblAciklama(Label lblAciklama) {
this.lblAciklama = lblAciklama;
}

}

Artık VaadinComposite sınıfımız form tarafında kullanabilmemiz için hazır. Öyleyse form tarafında dönüp butonumuzun buttonClick() metodunda neler yapabileceğimize bir bakalım;

Önce VaadinComposite objemizi oluşturalım:

public void buttonClick(ClickEvent event) {
VaadinComposite vaadinComposite = new VaadinComposite();
}

Hatırlarsanız composite sınıf içersinde ad,soyad ve aciklama label alanları için getter/setterlar tanımlamıştık. Şimdi bu getter’lar vasıtasıyla üç alanın da caption’larını tek tek form değerlerine setleyeceğiz(burada setlediğimiz componentlerin buttonClick metodu içinde çağırıldığından final olmaları gerektiğine dikkat edin). Bunun için her bir label’ı getter’ı ile çağırarak setCaption() metodu ile caption setleyeceğiz:

public void init() {
Window formPenceresi = new Window("Kodcu.Com Vaadin Form Penceresi");
setMainWindow(formPenceresi);

Form formum = new Form();
formum.setCaption("Bilgi Formu");
formPenceresi.addComponent(formum);

final TextField txtAdi = new TextField("Adı");
final TextField txtSoyadi = new TextField("Soyadı");
final TextArea txtAciklama = new TextArea("Açıklama");
Button btnGonder = new Button("Gönder");
btnGonder.addListener(new ClickListener() {

public void buttonClick(ClickEvent event) {
VaadinComposite vaadinComposite = new VaadinComposite();
vaadinComposite.getLblAdi().setCaption((String) txtAdi.getValue());
vaadinComposite.getLblSoyadi().setCaption((String) txtSoyadi.getValue());
vaadinComposite.getLblAciklama().setCaption((String) txtAciklama.getValue());
}
});

formum.getLayout().addComponent(txtAdi);
formum.getLayout().addComponent(txtSoyadi);
formum.getLayout().addComponent(txtAciklama);
formum.getLayout().addComponent(btnGonder);
}

Ardından bu composite componenti “formPenceresi” isimli penceremiz içine ekliyoruz:

public void buttonClick(ClickEvent event) {
VaadinComposite vaadinComposite = new VaadinComposite();
vaadinComposite.getLblAdi().setCaption((String) txtAdi.getValue());
vaadinComposite.getLblSoyadi().setCaption((String) txtSoyadi.getValue());
vaadinComposite.getLblAciklama().setCaption((String) txtAciklama.getValue());

formPenceresi.addComponent(vaadinComposite);
}

Uygulamamızın son halini çalıştıralım ve formu dolduralım:

Ve “Gönder” butonuna tıkladığımızda sonuç:

Bir sonraki yazımda görüşmek üzere. Esenlikle kalın…

Yorum yapabilirsiniz..


Benzer Yazılar

Yazar : Mehmet Aykut Bulgu

M. Aykut BULGU İstanbul doğumludur. Liseyi Kadıköy Anadolu Lisesi’nde okumuş, ardından İstanbul Teknik Üniversitesi Matematik Mühendisliği bölümünü bitirmiştir. PHP, .NET, JSP, Struts, JSF, Vaadin gibi web teknolojileri ile çalışmasının yanı sıra BPM, Rule Management, PDF Forms konularında açık kaynak yaklaşımlarla çalışmışlığı vardır. TDD, Scrum, EXtreme Programming, CI, Design Patterns konularında da bilgi sahibidir, ve halen daha kendini bu konularda geliştirmektedir. MIS uygulamalarına ve BPM uygulamalarına da özel bir ilgisi vardır. Open source teknoloji hastasıdır, bilgi özgürlüğüne can-ı gönülden katılır. Evinde Linux türevlerini kullanır. Pratik psikoloji ile çokça ilgilenmekte, boş zamanlarında yazılıma ayırdığı vakitler dışında NLP, Hipnoz, Sleight of Mouth, Koçluk, Beden ve Yüz dili gibi konularda araştırma yapmaktadır. Dile olan ilgisi nedeniyle şiir yazmışlığı da vardır.

En son haber ve ücretsiz eğitimlere ulaşmak için üye olabilirsiniz