`
duker
  • 浏览: 105630 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

gwt 实现界面模式之 "Extras on Demand"

    博客分类:
  • GWT
阅读更多

GWT 是一个强大的工具, 一旦定义好html结构和css之后,使用gwt提供的组件模型,可以将任意结构的html+css封装成为组件 ,并在java 语言中以组件的方式操作.GWT 1.6 增加了新的事件系统(原有的事件api可能会在将来删除), 更使得在dom或者现有的组件之上扩展开发相当容易.下面将以一个例子说明如何使用新的事件模型扩展现有组件.

(使用最新的 gwt 1.6.4 )

 

目标:


如上, 在google 财经中有一个最近查询的股票列表,当鼠标在上面移动时,仅有当前行的操作(删除)出现,这有点类似界面模式中的"Extras on Demand ". 我们的目标就是要在gwt 中实现类似的特性..

解决方案

相比较自己完全从html结构开始做起,如果能够在一个现有的组件之上进行开发,会减轻不少工作量,gwt 中提供了很多灵活,强大的组件.FlexTable 就是其中之一.FlextTable 很适合数据量不大的少量表格数据显示.也适合作为灵活的布局容器,如果需要显示大量数据,可以考虑 gwt incubator 中的 PagingScrollTable.

实现以上特性的关键是要能捕获鼠标移动事件(MouserMoveEvent), 并处理. FlexTable 支持ClickEvent, 并且可以使用 getCellForEvent 方法获得事件发生时的单元格对象,进而获得所在行. 当并不支持MouseMoveEvent. 所以首先我们需要从FlexTable 继承,并增加MouseMoveEvent 的事件支持.

public class MouseMoveableFexTable extends FlexTable implements HasMouseMoveHandlers, HasMouseOverHandlers,
        HasMouseOutHandlers {

    public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
        return addDomHandler(handler, MouseMoveEvent.getType());
    }

    public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
        return addDomHandler(handler, MouseOverEvent.getType());
    }

    public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
        return addDomHandler(handler, MouseOutEvent.getType());
    }

 增加事件处理在新的事件模型下就是如此简单,基本上不再需要去处理 onBrowserEvent 了,增加一个 HasXXX handler 的接口,然后在实现方法中加上一句 addDomHandler即可.我们同时实现了HasMouseOverHandlers,HasMouseOutHandlers. 因为希望在鼠标进入或者离开表格区域时,客户端也能检测到,并做相应的处理.

 

接下来我们需要象FlexTable 处理ClickEvent 一样,从MouseEvent 中返回所在的单元格信息

public class TableCell {

        int rowIdx;
        int colIdx;

        public TableCell(int rowIdx, int colIdx) {
            this.rowIdx = rowIdx;
            this.colIdx = colIdx;
        }

        public int getColIdx() {
            return colIdx;
        }

        public void setColIdx(int colIdx) {
            this.colIdx = colIdx;
        }

        public int getRowIdx() {
            return rowIdx;
        }

        public void setRowIdx(int rowIdx) {
            this.rowIdx = rowIdx;
        }
    }

    public TableCell getTableCellForEvent(DomEvent event) {
        Element td = getEventTargetCell(Event.as(event.getNativeEvent()));
        if (td == null) {
            return null;
        }
        Element tr = DOM.getParent(td);
        Element body = DOM.getParent(tr);
        int row = DOM.getChildIndex(body, tr);
        int column = DOM.getChildIndex(tr, td);

        return new TableCell(row, column);
    }

 首先定义了一个TableCell 内部类,用于传递单元格信息,之后定义一个 getTableCellForEvent 用于将事件转换成为单元格信息. 实现了这个功能后, 客户端就能注册 MouseMoveHandler, MouseOutHandler, 接收事件,提取当前的单元格信息,进而实现相应的程序操作了.

 

完整的代码如下:

/**
 * This code is released under lgpl v3 license.
 * All rights reserved.
 */
package net.gwidgets.client;

import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.HasMouseMoveHandlers;
import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlexTable;

/**
 * 
 * @author yuan yunchang    dukerr@gmail.com
 */
public class MouseMoveableFexTable extends FlexTable implements HasMouseMoveHandlers, HasMouseOverHandlers,
        HasMouseOutHandlers {

    public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
        return addDomHandler(handler, MouseMoveEvent.getType());
    }

    public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
        return addDomHandler(handler, MouseOverEvent.getType());
    }

    public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
        return addDomHandler(handler, MouseOutEvent.getType());
    }

    public class TableCell {

        int rowIdx;
        int colIdx;

        public TableCell(int rowIdx, int colIdx) {
            this.rowIdx = rowIdx;
            this.colIdx = colIdx;
        }

        public int getColIdx() {
            return colIdx;
        }

        public void setColIdx(int colIdx) {
            this.colIdx = colIdx;
        }

        public int getRowIdx() {
            return rowIdx;
        }

        public void setRowIdx(int rowIdx) {
            this.rowIdx = rowIdx;
        }
    }

    public TableCell getTableCellForEvent(DomEvent event) {
        Element td = getEventTargetCell(Event.as(event.getNativeEvent()));
        if (td == null) {
            return null;
        }
        Element tr = DOM.getParent(td);
        Element body = DOM.getParent(tr);
        int row = DOM.getChildIndex(body, tr);
        int column = DOM.getChildIndex(tr, td);

        return new TableCell(row, column);
    }
}

 

这是一个基于以上基础的demo:


完整的代码如下:

java module file:

/**
 * This code is released under lgpl v3 license.
 * All rights reserved.
 */
package net.gwidgets.demo.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import net.gwidgets.client.MouseMoveableFexTable;

/**
 *
 * @author yuan yunchang    dukerr@gmail.com
 */
public class MouseMoveControl implements EntryPoint {

    int currentRow = -1;
    MouseMoveableFexTable tb;

    public void onModuleLoad() {
        createTest();
    }

    private void createTest() {
        tb = new MouseMoveableFexTable();
        tb.setStylePrimaryName("testTable");
        
        tb.setText(0, 0, "名称");
        tb.setText(0, 1, "价格");
        tb.setText(0, 2, "涨跌");
        tb.getRowFormatter().addStyleName(0, "title");


        tb.setText(1, 0, "中国银行");
        tb.setText(1, 1, "3.53");
        tb.setText(1, 2, "-0.03 (-0.84%)");
        DelControl del = new DelControl("x");
        del.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                delRow(currentRow);
            }
        });
        tb.setWidget(1, 3, del);
        tb.getRowFormatter().addStyleName(1, "data");

        tb.setText(2, 0, "中国石油");
        tb.setText(2, 1, "11.83");
        tb.setText(2, 2, "-0.10 (-0.84%)");
        del = new DelControl("x");
        del.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                delRow(currentRow);
            }
        });
        tb.setWidget(2, 3, del);
        tb.getRowFormatter().addStyleName(2, "data");

        tb.setText(3, 0, "宝钢股份");
        tb.setText(3, 1, "6.00");
        tb.setText(3, 2, "-0.01 (-0.17%)");
        del = new DelControl("x");
        del.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                delRow(currentRow);
            }
        });
        tb.setWidget(3, 3, del);
        tb.getRowFormatter().addStyleName(3, "data");

        tb.addMouseMoveHandler(new MouseMoveHandler() {

            public void onMouseMove(MouseMoveEvent event) {
                MouseMoveableFexTable.TableCell cell = tb.getTableCellForEvent(event);
                if (cell != null) {
                    int row = cell.getRowIdx();
                    if(row>0){
                        setCurrent(row);
                    }
                }
            }
        });
        tb.addMouseOutHandler(new MouseOutHandler() {
            public void onMouseOut(MouseOutEvent event) {
                hideCurrenDel();
            }
        });

        tb.getColumnFormatter().addStyleName(0, "name");
        tb.getColumnFormatter().addStyleName(1, "price");
        tb.getColumnFormatter().addStyleName(2, "updown");

        RootPanel.get("mouse_move").add(tb);

    }

    void setCurrent(int row) {
        hideCurrenDel();
        Widget w = tb.getWidget(row, 3);
        w.setVisible(true);
        currentRow = row;
        tb.getRowFormatter().addStyleName(row, "current");

    }
    void hideCurrenDel(){
        if (currentRow > 0) {
            Widget prew = tb.getWidget(currentRow, 3);
            prew.setVisible(false);
            tb.getRowFormatter().removeStyleName(currentRow, "current");
        }
    }
    void delRow(int row) {
        tb.removeRow(row);
        currentRow = -1;
    }

    class DelControl extends Label {

        public DelControl(String text, boolean wordWrap) {
            super(text, wordWrap);
            setStylePrimaryName("delControl");
            setVisible(false);
            setTitle("删除");
        }

        public DelControl(String text) {
            super(text);
            setStylePrimaryName("delControl");
            setVisible(false);
        }

        public DelControl() {
            setStylePrimaryName("delControl");
            setVisible(false);
        }
    }
}
 

html:

<!--

-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script type="text/javascript" language="javascript" src="mousemove_control/mousemove_control.nocache.js"></script>
        <style>
           
        </style>
    </head>
    <body>
        <div class="main">
            <h3>mouse move controls demo</h3>
            <div id="mouse_move" ></div>
        </div>
    </body>
</html>

 css:

.main{
    margin-left:5em;
    margin-right:5em;
}
#mouse_move{
    margin-top:1em;
}
.delControl{
    padding:1px 5px;
    border:1px solid #aaaaaa;
    cursor:pointer;
}
.testTable{
    cursor:default;
}
.testTable .current{
    background-color:#eeeeee;
}
.testTable .title{
    background-color:#E5ECF9;
}
.testTable .data{
    height:30px;
}
.testTable .name{
    width:100px;
}
.testTable .price{
    width:80px;
}
.testTable .updown{
    width:150px;
}
 

 

 

 

 

 

 

 

  • 大小: 65.7 KB
  • 大小: 57.3 KB
分享到:
评论
2 楼 duker 2009-05-29  
哦, 给个链接,看看..
1 楼 edokeh 2009-05-25  
gwt官方博客里面最近有篇文章讲到自定义控件的最佳实践,它不建议继承gwt自带的UI类,而建议用聚合的方式来做

相关推荐

    gwt开发实例实现

    - **Java-to-JavaScript编译器**:GWT的核心特性之一是它的编译器,它将Java代码转换为高效的JavaScript,使得开发者可以使用熟悉的Java语言进行前端开发。 - **Widget库**:GWT提供了一系列丰富的用户界面组件...

    使用gwt实现的一个模式框

    本文将深入探讨如何使用GWT实现一个模式框,并基于描述和标签,重点讲解GWT的ShowModalDialog功能及其应用。 GWT是一个开放源代码的Java SDK,它允许开发者使用Java语言编写客户端的Web应用,然后编译成优化过的...

    gwt 实现的一个简单计算器

    这个"gwt 实现的一个简单计算器"项目提供了一个基础的起点,适合初学者了解GWT的工作原理和开发流程。下面将详细介绍GWT、计算器实现的关键知识点以及如何在Eclipse环境中进行调试。 1. **GWT概述**: GWT允许...

    GWT实现文件上传文件上传

    标题 "GWT实现文件上传" 涉及到的技术核心是使用Google Web Toolkit(GWT)来处理客户端的文件上传功能。GWT是一款强大的开发工具,它允许开发者使用Java语言编写客户端的Web应用,然后自动编译成JavaScript,使得...

    GWT DEMO 增删改查

    总的来说,这个DEMO将演示如何使用GWT和SmartGWT实现一个基本的数据管理界面,包括创建新的记录,查看列表,编辑选定记录以及删除记录。通过学习和理解这个DEMO,初学者能够快速掌握GWT中的CRUD操作,并为以后的项目...

    gwt界面编写example源代码

    在GWT界面编写中,开发者可以利用GWT的组件模型创建复杂的用户界面,使用事件驱动编程处理用户交互,并通过GWT的异步RPC机制实现实时的数据交换。浏览器冲突的处理主要涉及对不同浏览器之间的差异进行适配,如CSS...

    gwt 练习 gwt学习

    3. **Java到JavaScript编译**:GWT的编译过程将Java源代码转化为优化的JavaScript,这个过程叫做"编译优化",分为开发模式和生产模式两种。 4. **UI设计**:GWT提供了Widget库,包含许多常见的UI元素,如按钮、...

    使用GWT实现文件上传功能

    在使用Google Web Toolkit (GWT) 开发Web应用时,实现文件上传功能是常见的需求。GWT 提供了 FormPanel 和 FileUpload 类来帮助开发者处理文件上传操作。这两个类允许用户选择文件并通过HTTP请求发送到服务器,同时...

    GWT快速开发(GWT) 是一个Java软件开发框架用于开发类似于Google Maps和Gmail的AJAX应用程序。GWT的设计参考Java AWT包设计,类命名规则、接口设计、事件监听等。你可以用Java编程语言开发你的界面,然后用GWT编译器将Java类转换成适合浏览器执行的...

    - 使用GWT的UI组件构建用户界面,通过RPC实现与服务器的数据交互。 #### 五、总结 通过以上介绍可以看出,GWT提供了一个强大而灵活的开发框架,使得开发者能够使用Java语言构建出高质量的AJAX应用程序。无论是...

    一个gwt实现的客户管理系统

    通过分析和理解这个项目,开发者可以学习到如何利用GWT进行模块化开发、构建用户界面、实现服务器端与客户端的通信、以及如何设计和实现CRM系统的关键功能。此外,源代码还为开发者提供了深入研究GWT的最佳实践和...

    gwt实例,基于gwt-windows-1.5.2

    5. **与后台互动**:GWT通过Remote Procedure Calls (RPC)机制实现了客户端与服务器端的通信。当用户在客户端执行某些操作时,GWT会自动将请求转化为HTTP请求发送到服务器,服务器处理后返回结果,再由GWT解析并更新...

    GWT实现多个搜索引擎结果的聚集

    标题 "GWT实现多个搜索引擎结果的聚集" 涉及到的是使用Google Web Toolkit (GWT) 开发一个能够整合并展示多个搜索引擎结果的应用。GWT 是一个由Google开发的开源JavaScript框架,它允许开发者使用Java语言来编写前端...

    GWT

    通常,这样的设计可能涉及到如何优雅地组织GWT代码结构、实现可重用的组件或遵循特定的设计原则,如MVP(Model-View-Presenter)模式,用于分离视图逻辑和业务逻辑。 标签“源码”和“工具”表明这篇博客可能探讨了...

    GWT.rar_On Purpose_gwt

    **标题:“GWT.rar_On Purpose_gwt”** 这个标题表明我们关注的是Google Web Toolkit (GWT)的一个特定主题,即其“目的”。"On Purpose"可能是指深入理解GWT的设计理念、应用场景以及如何有效地利用它来开发Web应用...

    GWT入门 GWT中文教程

    首先,EXT-GWT2.0.1是EXT-GWT(GWT-Ext)的一个版本,它是基于GWT的组件库,提供了丰富的用户界面组件,如表格、树形视图、菜单等,使得开发者可以构建出具有桌面级用户体验的Web应用。EXT-GWT的API和DOC文档对于...

    关于GWT的部署介绍

    在这个模式下,开发者可以在 Java 虚拟机中使用 GWT 内置的浏览器模拟器运行未转换的 Java 代码,实现快速的“编码、测试、调试”循环。启动宿主模式可以通过运行 `com.google.gwt.dev.GWTShell` 命令实现。 【Web ...

    gwt之分页控件

    在这个“gwt之分页控件”的主题中,我们将深入探讨GWT中如何实现高效且用户友好的分页功能。 首先,我们需要理解GWT的基本工作原理。GWT将Java代码编译成JavaScript,使得开发者可以在浏览器环境中运行Java应用,而...

    GWT入门和进阶

    此外,MVP(Model-View-Presenter)模式是GWT中推荐的架构模式,它分离了用户界面、视图逻辑和业务逻辑。 **5. RPC通信** GWT提供了Remote Procedure Call (RPC)机制,使得客户端和服务器之间可以进行安全的数据...

Global site tag (gtag.js) - Google Analytics