RSS

Interfaz de usuario y eventos en GWT

21 may

Visit my new website http://java4developers.com

Como veíamos en el post ejemplo básico con GWT vamos a continuar con la creación de una interfaz de usuario sencilla y con la gestión de los eventos en un cliente GWT que se hace de ella. Para este post vamos a seguir el tutorial básico de la página de GWT.


Lo primero que tenemos que hacer es modificar nuestra página html de inicio para añadir una capa donde se cargue nuestro remozado cliente GWT. Para ello nos vamos a la carpeta war de nuestro proyecto y tendremos que editar el fichero StockWatcher.html de la siguiente forma:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="StockWatcher.css">
    <title>StockWatcher</title>
    <script type="text/javascript" language="javascript" src="stockwatcher/stockwatcher.nocache.js"></script>
  </head>
  <body>
    <h1>StockWatcher</h1>
    <div id="stockList"></div>
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
  </body>
</html>

y modificaremos nuestra clase StockWatcher.java para añadir todos los componentes visuales de nuestra interfaz de usuario.

package com.google.gwt.sample.stockwatcher.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class StockWatcher implements EntryPoint {

  private VerticalPanel mainPanel = new VerticalPanel();
  private FlexTable stocksFlexTable = new FlexTable();
  private HorizontalPanel addPanel = new HorizontalPanel();
  private TextBox newSymbolTextBox = new TextBox();
  private Button addStockButton = new Button("Add");
  private Label lastUpdatedLabel = new Label();

  /**
   * Entry point method.
   */
  public void onModuleLoad() {
    // Create table for stock data.
    stocksFlexTable.setText(0, 0, "Symbol");
    stocksFlexTable.setText(0, 1, "Price");
    stocksFlexTable.setText(0, 2, "Change");
    stocksFlexTable.setText(0, 3, "Remove");

    // Assemble Add Stock panel.
    addPanel.add(newSymbolTextBox);
    addPanel.add(addStockButton);

    // Assemble Main panel.
    mainPanel.add(stocksFlexTable);
    mainPanel.add(addPanel);
    mainPanel.add(lastUpdatedLabel);

    // Associate the Main panel with the HTML host page.
    RootPanel.get("stockList").add(mainPanel);

    // Move cursor focus to the input box.
    newSymbolTextBox.setFocus(true);

  }

}

Podemos ver como hemos creado nuestra interfaz entorno a tres componentes:

  • FlexTable: donde vamos a guardar los elementos que van a cotizar en nuestra ‘bolsa’
  • HorizontalPanel: que nos permitirá introducir nuevos valores en nuestra bolsa
  • Label: nos indicará la última fecha de actualización.

Una vez construida nuestra interfaz GWT vamos a darle funcionalidad creando y gestionando unos cuantos eventos. Para ello y dentro de la clase StockWatcher.java vamos a añadir un par de eventos:

 // Listen for mouse events on the Add button.
    addStockButton.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        addStock();
      }
    });

    // Listen for keyboard events in the input box.
    newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
      public void onKeyPress(KeyPressEvent event) {
        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
          addStock();
        }
      }
    });

Si añadimos un nuevo valor para que cotize en nuestra bolsa virtual y luego pinchamos el botón Add o bien damos un enter será addClickHandler ó addKeyPressHandler los que se encarguen de gestionar nuestro evento. Como podemos ver ambos llaman a la función addStock que va a tener el siguiente aspecto:

	private void addStock() {
		final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
		newSymbolTextBox.setFocus(true);

		// Stock code must be between 1 and 10 chars that are numbers, letters,
		// or dots.
		if (!symbol.matches("^[0-9A-Z\\.]{1,10}$")) {
			Window.alert("'" + symbol + "' is not a valid symbol.");
			newSymbolTextBox.selectAll();
			return;
		}

		newSymbolTextBox.setText("");

		// Don't add the stock if it's already in the table.
		if (stocks.contains(symbol))
			return;

		// Add the stock to the table.
		int row = stocksFlexTable.getRowCount();
		stocks.add(symbol);
		stocksFlexTable.setText(row, 0, symbol);

		// Add a button to remove this stock from the table.
		Button removeStockButton = new Button("x");
		removeStockButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				int removedIndex = stocks.indexOf(symbol);
				stocks.remove(removedIndex);
				stocksFlexTable.removeRow(removedIndex + 1);
			}
		});
		stocksFlexTable.setWidget(row, 3, removeStockButton);

		// Get the stock price.
		refreshWatchList();
	}

Este método recoge el nombre que queremos dar a nuestra empresa para que cotice en la bolsa, realiza una validación de su nombre, mira si ya estaba previamente insertada y la añade a la nuestra tabla. Además le añade un botón de eliminar, por si a nuestra empresa le da por quebrar (#spanishrevolution). Para refrescar los valores en nuestra tabla creamos el método refreshWatchList:

  /**
   * Generate random stock prices.
   */
  private void refreshWatchList() {
    final double MAX_PRICE = 100.0; // $100.00
    final double MAX_PRICE_CHANGE = 0.02; // +/- 2%
    StockPrice[] prices = new StockPrice[stocks.size()];
    for (int i = 0; i < stocks.size(); i++) {
      double price = Random.nextDouble() * MAX_PRICE;
      double change = price * MAX_PRICE_CHANGE
          * (Random.nextDouble() * 2.0 - 1.0);
      prices[i] = new StockPrice(stocks.get(i), price, change);
    }
    updateTable(prices);
  }

Para actualizar las tablas necesitamos otros dos métodos más que simplemente actualizan las cotizaciones de nuestras empresas.

	  /**
	   * Update the Price and Change fields all the rows in the stock table.
	   *
	   * @param prices Stock data for all rows.
	   */
	  private void updateTable(StockPrice[] prices) {
	    for (int i = 0; i < prices.length; i++) {
	      updateTable(prices[i]);
	    }
	  }

	    /**
	     * Update a single row in the stock table.
	     *
	     * @param price Stock data for a single row.
	     */
	    private void updateTable(StockPrice price) {
	      // Make sure the stock is still in the stock table.
	      if (!stocks.contains(price.getSymbol())) {
	        return;
	      }

	      int row = stocks.indexOf(price.getSymbol()) + 1;

	      // Format the data in the Price and Change fields.
	      String priceText = NumberFormat.getFormat("#,##0.00").format(
	          price.getPrice());
	      NumberFormat changeFormat = NumberFormat.getFormat("+#,##0.00;-#,##0.00");
	      String changeText = changeFormat.format(price.getChange());
	      String changePercentText = changeFormat.format(price.getChangePercent());

	      // Populate the Price and Change fields with new data.
	      stocksFlexTable.setText(row, 1, priceText);
	      stocksFlexTable.setText(row, 2, changeText + " (" + changePercentText
	          + "%)");
	    }

Además necesitaremos una clase que encapsule toda la información referida a cada una de nuestras empresas.

package com.google.gwt.sample.stockwatcher.client;

public class StockPrice {

  private String symbol;
  private double price;
  private double change;

  public StockPrice() {
  }

  public StockPrice(String symbol, double price, double change) {
    this.symbol = symbol;
    this.price = price;
    this.change = change;
  }

  public String getSymbol() {
    return this.symbol;
  }

  public double getPrice() {
    return this.price;
  }

  public double getChange() {
    return this.change;
  }

  public double getChangePercent() {
    return 10.0 * this.change / this.price;
  }

  public void setSymbol(String symbol) {
    this.symbol = symbol;
  }

  public void setPrice(double price) {
    this.price = price;
  }

  public void setChange(double change) {
    this.change = change;
  }
}

Tendremos que añadir un timer en el método onModuleLoad que recargue los valores cotizados tras un cierto periodo.


public void onModuleLoad() {

    ...

    // Move cursor focus to the text box.
    newSymbolTextBox.setFocus(true);

    // Setup timer to refresh list automatically.
    Timer refreshTimer = new Timer() {
      @Override
      public void run() {
        refreshWatchList();
      }
    };
    refreshTimer.scheduleRepeating(REFRESH_INTERVAL);

    ...

  }

Lo último que vamos a añadir a nuestro código es la etiqueta con la fecha de modificación de nuestra bolsa.

  /**
   * Update the Price and Change fields all the rows in the stock table.
   *
   * @param prices Stock data for all rows.
   */
  private void updateTable(StockPrice[] prices) {
    for (int i = 0; i < prices.length; i++) {
      updateTable(prices[i]);
    }

    // Display timestamp showing last refresh.
    lastUpdatedLabel.setText("Last update : "
        + DateTimeFormat.getMediumDateTimeFormat().format(new Date()));

  }

Finalmente ejecutamos nuestra aplicación y vemos el resultado:
Manage events in GWT
Manage events in GWT 2

Si quieres añadir estilo con CSS a tu aplicación GWT te lo permite. Para ello echalé un vistazo al tutorial de aplicar estilo.

About these ads
 
7 comentarios

Publicado por en 21 mayo, 2011 en GWT

 

Etiquetas: , , ,

7 Respuestas a “Interfaz de usuario y eventos en GWT

  1. Ruth

    10 agosto, 2011 at 9:17 pm

    Hi Im trying to use you tutorial, but im having some issues.

    updateTable(StockPrice[] prices) seems to be declared three times. Im not sure if I should put all the code in only one function

    also the declaration of stocks its missing, I dont have idea at which class/type belongs

    // Don’t add the stock if it’s already in the table.
    if (stocks.contains(symbol))

    Could you please check the chuck of code that you posted, there its not possible for me to figure whats missing out

    thanks

     
    • hop2croft

      10 agosto, 2011 at 10:19 pm

      Hi Ruth,

      thanxs for reading my blog. I promise rewriting this post in English tomorrow. Anyway the method updateTable has two different signatures:

      • updateTable(StockPrice[] prices)
      • updateTable(StockPrice price)

      You have two use both in order to updating the stock prices in the table. The last updateTable(StockPrice[] prices) chunk of code is the same that the first one plus a new label that shows when the table was last refreshed. The definitive code should looks like this:

      private void updateTable(StockPrice[] prices) {
        for (int i = 0; i < prices.length; i++) {
          updateTable(prices[i]);
        }
      
        // Display timestamp showing last refresh.
        lastUpdatedLabel.setText("Last update : "
            + DateTimeFormat.getMediumDateTimeFormat().format(new Date()));
      
      }
      
      
        /**
         * Update a single row in the stock table.
         *
         * @param price Stock data for a single row.
         */
        private void updateTable(StockPrice price) {
          // Make sure the stock is still in the stock table.
          if (!stocks.contains(price.getSymbol())) {
            return;
          }
      
          int row = stocks.indexOf(price.getSymbol()) + 1;
      
          // Format the data in the Price and Change fields.
          String priceText = NumberFormat.getFormat("#,##0.00").format(
              price.getPrice());
          NumberFormat changeFormat = NumberFormat.getFormat("+#,##0.00;-#,##0.00");
          String changeText = changeFormat.format(price.getChange());
          String changePercentText = changeFormat.format(price.getChangePercent());
      
          // Populate the Price and Change fields with new data.
          stocksFlexTable.setText(row, 1, priceText);
          stocksFlexTable.setText(row, 2, changeText + " (" + changePercentText
              + "%)");
        }
      
       
  2. Andrea

    28 noviembre, 2011 at 10:54 pm

    Hola, muchas gracias por el tutorial.Pero tengo una pregunta:
    Cada vez que cree una interfaz gráfica tengo que crear una clase que encapsule la información..

     
    • hop2croft

      28 noviembre, 2011 at 11:18 pm

      Hola, gracias a ti por leer el blog!!.

      La respuesta corta es sí :). La larga es que en GWT si quieres mostrar renderizados componentes HTML como botones, cajas de texto, … necesitas crearte una clase ‘Composite’ que implemente EntryPoint. Además necesitarás sobreescribir el método onModuleLoad() y será aquí donde indiques que componentes vas a incluirás. Esta clase java se tendrá que añadir al fichero *.gwt.xml.

      Echale un ojo a este link http://code.google.com/intl/es-ES/webtoolkit/doc/1.6/DevGuideUserInterface.html. En la sección Creating Custom Widgets te indican las formas de crear un nuevo Widget, se explica la forma indicada en este post y dos más. Aunque estas dos son menos comunes, quizá te pueda interesar.

      Un saludo.

       

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 69 seguidores

A %d blogueros les gusta esto: