Vaadin Web应用开发教程(5):Vaadin Web应用的基本组成部分

jerry VaadinWeb 2015年11月25日 收藏

上篇博客Vaadin Web应用开发教程(4):开始编写Web应用 介绍了一个最简单的Vaadin应用。一般来说,一个Vaadin应用由下面几个部分构成:

  • Windows  每个Web应用都有一个主窗口。主窗口(Main windows) 为应用程序级窗口,或是指UI层次的根元素。实际上Web应用可以包含多个应用程序级(application level)窗口,这些窗口都和Application对象关联。 每个根窗口还可以包含多个子窗口。
  • UI组件 ,每个应用的用户界面都由这些UI组件组合而成,用户通过这些UI组件和应用程序交互,用户通过UI组件触发事件,Web应用通过事件处理函数来响应用户。大部分的UI组件支持数据绑定。这些UI组件包括Label,Button,Checkbox等,程序员可以通过继承或组合来定义用户界面。
  • Events和Listener  Event为事件,Listener用来处理事件。
  • 资源 应用程序可以在页面上显示图像,超链接等,这些为资源文件,Vaadin支持多种资源种类。
  • 显示主题 Vaadin将UI显示的表述(Presentation)和逻辑(Logic)分开. 其中UI逻辑由对应的Java代码处理。而采用主题通过CSS来定义UI显示。Vaadin内置多种显示主题,开发人员也可自定义主题。
  • 数据绑定 Vaadin 定义了数据模型,使用这种数据模型,UI组件可以绑定到数据源,比如变量,数组,数据库的表。

主窗口

一般来说一个Vaadin Web应用只有一个主窗口(Main Windows)。 一般在Application对象中通过setMainWindow() 设置主窗口。

  1. import com.vaadin.ui.*;
  2.  
  3. public class HelloWorld extends com.vaadin.Application {
  4. public void init() {
  5. Window main = new Window("The Main Window");
  6. setMainWindow(main);
  7.  
  8. ... fill the main window with components ... }}

定义了主窗口之后,可以通过主窗口的addComponent 为主窗口添加其它UI组件。这些UI组件将使用主窗口的缺省布局来排列UI组件,如果你需要使用其它布局方法,可以通过setContent()定义新的布局。

子窗口

Vaadin 的窗口有两种类型,一种为应用程序级(Application level)的窗口,如上面的主窗口,另外一种为子窗口,显示在某个应用程序级的窗口中。

子窗口的创建和关闭,子窗口也是Window对象,通过addWindow 添加到主窗口中,关闭子窗口是通过Application对象的removeWindow() 方法。

  1. //open a window
  2. mywindow = new Window("My Window");
  3. mainwindow.addWindow(mywindow);
  4. ...
  5. //close a window
  6. myapplication.removeWindow (mywindow);

子窗口缺省可以通过右上方的关闭按钮关闭,可以通过将子窗口设为readonly禁止用户提供关闭按钮关闭子窗口。

可以通过setHeight, setWidth ,setPositionX,setPositionY 来设置窗口的大小和在屏幕的位置。

  1. /* Create a new window. */
  2. mywindow = new Window("My Dialog");
  3. /* Set window size. */
  4. mywindow.setHeight("200px");
  5. mywindow.setWidth("400px");
  6. /* Set window position. */
  7. mywindow.setPositionX(200);
  8. mywindow.setPositionY(50);

如果子窗口的大小为固定或者通过比例定义,当它显示的内容过大时,会自动出现滚动条。但如果子窗口某方向大小为定义时,则其大小会自动适应需显示的内容而不会出现滚动条。

Vaadin的窗口也支持所谓模式窗口,通常对话框显示为模式窗口。下图为一模式窗口,其父窗口为灰色显示:

事件处理

Vaadin 事件处理也是通过为UI组件添加Listener的方法来实现的,使用Listener有三种基本用法,下面以一个Button为例来说明这几种基本用法。

这里定义一个事件处理类来处理Button的Click事件

  1. public class TheButton implements Button.ClickListener {
  2. Button thebutton;
  3.  
  4. /** Creates button into given container. */
  5. public TheButton(AbstractComponentContainer container) {
  6. thebutton = new Button ("Do not push this button");
  7. thebutton.addListener(this);
  8. container.addComponent(thebutton);
  9. }
  10.  
  11. /** Handle button click events from the button. */
  12. public void buttonClick (Button.ClickEvent event) {
  13. thebutton.setCaption ("Do not push this button again");
  14. }
  15. }

一个应用中通常需要处理来自同一个类的多个UI对象触发的事件,比如多个Button,此时在Listener中需要区分事件是由哪个Button触发的。Vaadin支持多种方法来解决这个问题。一是通过event的getButton 方法,如下:

  1. public class TheButtons implements Button.ClickListener {
  2. Button thebutton;
  3. Button secondbutton;
  4.  
  5. /** Creates two buttons in given container. */
  6. public TheButtons(AbstractComponentContainer container) {
  7. thebutton = new Button ("Do not push this button");
  8. thebutton.addListener(this);
  9. container.addComponent(thebutton);
  10.  
  11. secondbutton = new Button ("I am a button too");
  12. secondbutton.addListener(this);
  13. container.addComponent (secondbutton);
  14. }
  15.  
  16. /** Handle button click events from the two buttons. */
  17. public void buttonClick (Button.ClickEvent event) {
  18. if (event.getButton() == thebutton)
  19. thebutton.setCaption("Do not push this button again");
  20. else if (event.getButton() == secondbutton)
  21. secondbutton.setCaption("I am not a number");
  22. }
  23. }
  24.  

第二种方法是使用addListener 的另外一个重载方法,这个方法可以将事件处理方法做为参数。如下例,参数类型为字符串,为事件处理函数的名称。

  1. public class TheButtons2 {
  2. Button thebutton;
  3. Button secondbutton;
  4.  
  5. /** Creates two buttons in given container. */
  6. public TheButtons2(AbstractComponentContainer container) {
  7. thebutton = new Button ("Do not push this button");
  8. thebutton.addListener(Button.ClickEvent.class, this,
  9. "theButtonClick");
  10. container.addComponent(thebutton);
  11.  
  12. secondbutton = new Button ("I am a button too");
  13. secondbutton.addListener(Button.ClickEvent.class, this,
  14. "secondButtonClick");
  15. container.addComponent (secondbutton);
  16. }
  17.  
  18. public void theButtonClick (Button.ClickEvent event) {
  19. thebutton.setCaption ("Do not push this button again");
  20. }
  21.  
  22. public void secondButtonClick (Button.ClickEvent event) {
  23. secondbutton.setCaption ("I am not a number!");
  24. }
  25. }
  26.  

第三种方法为匿名函数方法,这也是最简单的一种方法,无需定义新的类来处理事件。如下:

  1. public class TheButtons3 {
  2. Button thebutton;
  3. Button secondbutton;
  4.  
  5. /** Creates two buttons in given container. */
  6. public TheButtons3(AbstractComponentContainer container) {
  7. thebutton = new Button ("Do not push this button");
  8.  
  9. /* Define a listener in an anonymous class. */
  10. thebutton.addListener(new Button.ClickListener() {
  11. /* Handle the click. */
  12. public void buttonClick(ClickEvent event) {
  13. thebutton.setCaption (
  14. "Do not push this button again");
  15. }
  16. });
  17. container.addComponent(thebutton);
  18.  
  19. secondbutton = new Button ("I am a button too");
  20. secondbutton.addListener(new Button.ClickListener() {
  21. public void buttonClick(ClickEvent event) {
  22. secondbutton.setCaption ("I am not a number!");
  23. }
  24. });
  25. container.addComponent (secondbutton);
  26. }
  27. }
  28.  

事件通常由系统触发,但也可以通过方法fireEvent 来触发某个事件。