Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >GWT表示层:谁做什么?

GWT表示层:谁做什么?
EN

Stack Overflow用户
提问于 2012-09-07 04:37:25
回答 3查看 1.3K关注 0票数 7

我正在学习GWT,并试图把我的注意力集中在所有的UI选项上。我试图弄清楚什么时候/哪里/如何使用小部件、UIBinder、和自定义小部件。具体地说:

  • GWT设计器生成什么作为输出?UIBinder XML?可以肯定地说,当您不想手动编写UIBinder XML时,可以使用GWT设计器,但它们都具有相同的确切用途吗?
  • 什么时候在小部件上使用UIBinder?是否小部件被翻译成UIBinder XML,但是有更多的代码(事件处理等等)?在他们身上?在这种情况下,我会假设UIBinder的优点是代码少,因此性能更快?在两者之间作出选择时,还应考虑其他因素吗?
  • 您是编写了大量的UIBinder XML“片段”,还是只将它们打包到一个大的完整的XML文件中?
  • 对于我自己的定制组件,扩展com.google.gwt.user.client.ui.*com.google.gwt.user.client.ui.Composite有什么区别?
  • 分工:Widget/UIBinder与布局与CSS文件:谁在做什么?

对我来说,我觉得所有这些事情都是一样的,也许这只是GWT为您提供多种方式来完成演示的方式?如果没有,请在这些项目上纠正我。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-07 06:19:29

  • 只有当小部件非常简单时,我才在UiBinder上使用小部件。例如,我只是在Panel中添加两个小部件。如果涉及到任何CSS,我总是使用UiBinder,因为使用样式要容易得多。
  • 小部件不会被转换为UiBinder XML。所有的GWT代码都变成了添加和操纵DOM元素的JavaScript,所以所有东西都被转换成可执行语言,而不是模板系统。
  • 我写了很多UiBinder片段。我试着遵循好的关于抽象和合成的规则,你可以在网上找到它们。
  • 如果您有任何非平凡的逻辑,则MVP模式是必须的,因为使用JUnit测试GWT无关的演示程序非常快速和容易,而GWT测试的开销要大得多,而且要慢得多。
  • 我喜欢尽可能多地使用CSS文件的样式,因为分离关注点是一个标准的良好实践,您可以压缩和打包CSS文件,还有许多其他原因,这些原因与在普通HTML页面中将CSS放在单独的文件中而不是直接放在页面上的原因相同。
  • 我从不使用GWT设计器。我总是喜欢有干净的代码,而不是疯狂的垃圾通常被任何UI代码生成器吐出来。
  • 99%的情况下,我的小部件扩展了Composite,因为我要么使用UiBinder,要么向Panel添加东西。即使我只有一个小部件,我也发现扩展Composite并将我的一个小部件添加到SimplePanel中更容易。我很少扩展Widget,因为您必须调用Document.get().createFooElement()来创建DOM Element,但是我通常会发现Widgets (可以添加到Panels )比Element的更容易使用。

我如何构造小部件

每个小部件实现一个扩展IsWidget的接口。每个想要使用Widget的人都应该依赖于接口,而不是底层类。这提供了一个单独的、不含JSNI的抽象。

如果小部件非常简单,我将有一个扩展Composite并实现接口的类。小部件将非常简单,并将一些项添加到Panel中,或者它将使用UiBinder。

如果小部件具有我想要测试的非平凡逻辑,我使用MVP模式。将有一个演示类实现小部件的“公共”接口,一个视图接口扩展了演示者所依赖的IsWidget,以及一个实现视图接口的视图小部件。

为小部件拥有一个“公共”接口的好处是,如果逻辑变得复杂,您可以从使用单个Composite类实现接口改为使用MVP,而且使用小部件的人根本不需要更改。

我使用Gin将所有接口和实现连接在一起。

示例

这最好用一些代码来解释。假设我有一个图表,我想在几个页面上使用,所以我决定为它制作一个可重用的小部件。在显示RPC响应之前,有一些重要的逻辑需要处理,所以我想彻底地对它进行单元测试。我会做这样的事情:

代码语言:javascript
运行
AI代码解释
复制
public interface FinancialChart extends IsWidget {
  void setTickerSymbol(String tickerSymbol);
}

class FinancialChartPresenter extends Composite implements FinancialChart {
  private final FinancialChartView view;      
  private final DataServiceAsync service;

  @Inject(FinancialChartView view, DataServiceAsync service) {
    this.view = view;
    this.service = service;
  }

  @Override public Widget asWidget() {
    return view.asWidget();
  }

  @Override public void setTickerSymbol(String tickerSymbol) {
    service.getData(tickerSymbol, new AsyncCallback<FinancialData>() {
      @Override public void onFailure(Throwable t) {
        // handle error
      }

      @Override public void onSuccess(FinancialData data) {
        SimpleData simpleData = // do some parsing with presentation-specific
          // logic, e.g. make dramatic increases or decreases in price have a
          // a different color so they stand out.  End up with something simple
          // that's essentially some (x, y) points that the dumb view can plot
          // along with a label and color for each point.
        view.drawGraph(simpleData);
      }
  }
}

interface FinancialChartView extends IsWidget {
  void drawGraph(SimpleData simpleData);
}

class FinancialChartWidget extends Composite implements FinancialChartView {
  @Override public void drawGraph(SimpleData simpleData) {
    // plot the points on a chart.  set labels.  etc.
  }
}

class SomethingWithFinancialChartWidget extends Composite
    implements SomethingWithFinancialChart {
  interface Binder extends UiBinder<Widget, SomethingWithFinancialChartWidget> {}

  @UiField(provided = true) final FinancialChart chart;

  @Inject SomethingWithFinancialChartWidget(Binder binder, FinancialChart chart) {
    this.chart = chart;
    initWidget(binder.createAndBindUi(this));
  }
}

// In SomethingWithFinancialChartWidget.ui.xml
<ui:HTMLPanel>
  <!-- lots of stuff -->
  <mynamespace:FinancialChart ui:field="chart" />
  <!-- lots more stuff -->
</ui:HTMLPanel>

class MyPackagesGinModule extends AbstractGinModule {
  @Override protected void configure() {
    bind(FinancialChart.class).to(FinancialChartPresenter.class);
    bind(FinancialChartView.class).to(FinancialChartWidget.class);
  }
}

这允许我为JUnit编写非常简单、彻底和快速的FinancialViewPresenter测试,因为它没有GWT依赖项,需要JSNI,它必须在浏览器中运行,作为GWT测试用例的一部分。您可以创建一个模拟FinancialChartView

这里需要注意的一点是,由于SomethingWithFinancialChartWidget依赖于接口FinancialChart,所以它不能实例化该对象,因为它只是一个接口。这就是为什么在chartSomethingWithFinancialChartWidget代码中将SomethingWithFinancialChartWidget设置为@UiField(provided = true)的原因。Gin将从FinancialChart接口绑定到一个具体的类,这样它就可以向SomethingWithFinancialChartWidget@Inject构造函数提供一个实现,然后设置this.chart就可以为UiBinder提供它需要的对象。

有许多文件是为MVP中的所有接口和实现创建的,但是抽象是绝对值得的,因为它们支持对演示者进行简单的单元测试,并允许您更改顶层接口FinancialChart在本例中的实现方式,例如从单个Composite类更改为MVP,而不需要更改客户端。

我确信有些实现细节可能不太清楚,或者我忽略了一些事情,例如GWT测试,所以请发表评论,我可以编辑我的答案来更新和澄清。

票数 5
EN

Stack Overflow用户

发布于 2012-09-07 07:48:27

让我们与你的问题保持距离,并立即回答整体关心的问题。但首先,我最喜欢的口号是:

没有魔法!

UiBinder是一种获取XML定义并从中生成Java代码的工具。也就是说(通过调用GWT.create()构建的一切都是这样的:没有魔法!)你可以用Java代码手工写同样的东西。换句话说,UiBinder只是一个工具,可以通过减少代码来实现相同的目标,从而使更有效率。但是,当它生成您可以手工编写的代码时,它不会在运行时提供更好的性能(也不会更糟);然而,它使使用能够提高性能的模式变得更容易,即HTMLPanel:在纯Java中维护HTMLPanel-based代码是一场噩梦,与UiBinder完全相反。

UiBinder将:

  • 生成隐式ClientBundle,为每个<ui:style>生成隐式CssResource,为每个<ui:image>生成隐式ImageResource,为每个<ui:data>生成隐式DataResource
  • 为I18N生成一个隐式<ui:msg>接口,<ui:ph>等。
  • 根据XML中的ui:field属性和ui:field代码中的@UiField注释,将对象注入合作伙伴对象的字段(称为所有者,并作为参数传递给provided=true方法);如果注释具有provided=true,则可能从合作伙伴对象中检索对象。
  • 使用各种专用解析器、@UiConstructor-annotated构造函数或合作伙伴对象的@UiFactory-annotated方法创建对象,或者使用GWT.create()调用作为最后手段。
  • 将合作伙伴对象的@UiHandler-annotated方法绑定为XML模板中的小部件的事件处理程序(基于ui:field属性)
  • 最后但并非最不重要的一点是:将所有已构造的对象组装在一起,并设置它们的一些属性(XML中的属性外)。

UiBinder最常见的用法是我上面提到的对象都是小部件。然后组装它们意味着将小部件添加到其他容器小部件中。

这就是为什么您通常看到UiBinder在Composite中被用于为initWidget()方法提供值: UiBinder将创建并组合所需的所有小部件,并返回最顶部的小部件,作为复合小部件的根。

您已经理解了:您不会在小部件上使用UiBinder,也不会将小部件转换为UiBinder XML (实际上正好相反)。

现在让我们来问一些更具体的问题:

您是编写了大量的UIBinder XML“片段”,还是只将它们打包到一个大的完整的XML文件中?

UiBinder是一种实现细节。大多数情况下,您将使用UiBinder构建(可重用的)小部件(复合);它不会扩展到外部世界,它只会看到一个小部件,而不是“用UiBinder构建的东西”。

这意味着您将拥有大量的中小型UiBinder模板(通常在应用程序中每个屏幕上都有一个模板,或者更一般的规则是,每个复杂UI组件一个)。

对于我自己的定制组件,扩展com.google.gwt.user.client.ui.*与扩展com.google.gwt.user.client.ui.Composite有什么区别?

麻省理工学院回答了这个问题,同时也回答了文档:https://developers.google.com/web-toolkit/doc/latest/DevGuideUiCustomWidgets

分工:Widget/UIBinder与布局与CSS文件:谁在做什么?

不幸的是,这个问题没有简单的答案。那得看情况。

这取决于您正在构建的应用程序类型,以及您想要的UI类型。对于应用程序的“全局布局”,您将使用多个RootPanel或一个大HTMLPanel,并使用HTML和CSS进行布局(或者在HTML主页中,或者在UiBinder模板中充当应用程序的外壳),或者使用所谓的版面板

对于更多的本地化布局(在复合小部件中),我建议使用HTMLPanelFlowPanel;或者可能使用布局面板。如果需要处理滚动事件,或者需要在容器小部件内滚动,则使用ScrollPanel,否则只需在CSS中使用overflow: scroll

是有权衡的。你得做实验。最后,使用您认为对您有好处的。没有一刀切的东西。

最后,尽管它是最常见的用例,但是请注意,UiBinder可以不使用小部件,例如用于创建非复合小部件 (或UiObjects,但它们的用例很少;例如,您将看到它们用于MenuItems和TreeItems ),使用setElement()而不是initWidget()创建自定义单元格

实际上,Composite的用例也不多:您可以简单地实现IsWidget (返回createAndBindUi的结果,调用一次并缓存在私有字段中),并且它应该在任何需要/接受小部件的地方工作。

票数 2
EN

Stack Overflow用户

发布于 2012-09-07 06:36:56

  1. 你是对的。GWT输出UIBinder XML代码。java代码只是一种声明性语法,它可以转换成实际的UIBinder代码(就像您要在Java类中创建元素一样)。
  2. UIBinder和小部件在某种程度上是不可比拟的。您可以使用UiBinder与普通Java代码一起创建小部件,但是您可以使用相同的功能实现相同的小部件,只能使用java代码。UiBinder只是使它更具可读性,因为它是声明性的,并且您最终不会实例化许多UI元素(即TextBox textbox = new TextBox();container.add(textBox))。
  3. 对于组件和小部件,我将使用单独的UiBinder片段,并将它们放到父UIBinder文件(即Presenter)中。但是,将每一个微小的组件(即表单的标签+ TextBox )放入单独的UIBinder片段可能是没有意义的。您必须找到一个很好的平衡(尽管在本例中,如果您广泛使用TextBox,可以创建Label +UiBinder组件)。
  4. 如果您创建了一个由现有组件组成的新组件,请使用Composite。如果您创建了一个唯一的新小部件或组件,不能使用现有的小部件或组件,请使用WidgetIsWidget
  5. 我通常这样做:

  • 尽可能多地使用UIBinder。例如,对页面结构使用LayoutPanels
  • 为您在整个应用程序中使用的通用样式创建一个主ClientBundleCSSResource
  • 当您需要只使用一次的特定样式时,将<ui:style>声明放入相应的UiBinder文件中。
  • 为可重用组件创建小部件(同样,您可以遵循以下3点)。

最后,Michael提出了一些关于MVP和测试的优点。我强烈建议跟随他们。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12318266

复制
相关文章
OpenAI老板推特说相声:嘲笑创投圈「募6轮资还没到A轮」
创业公司募资化缘一轮接一轮、同时迟迟不出货没进展的恶劣风气,现在已是妇孺皆知。虽然初创公司过去一般在筹集 A、B、C 等轮次之前先进行种子轮融资,但现在许多公司选择在其间进行额外的轮次。
新智元
2022/02/24
4480
OpenAI老板推特说相声:嘲笑创投圈「募6轮资还没到A轮」
MeshCloud 脉时云获 1 亿元 A+ 轮融资
2021年11月23日,出海融合云服务商MeshCloud脉时云(www.mesh.com.cn)宣布完成1亿元A+轮融资。 MeshCloud脉时云公司名为北京云联万维技术有限公司,成立于2017年,基于MeshCloud融合云SaaS平台、出海音视频/游戏/电商等行业垂直解决方案、高效的服务体系、海外公有云厂商的深度合作,以及自建海外云基础设施为中企出海提供高质量、低成本、敏捷部署的一站式产品和服务。 此轮融资由贵州省创新赋能大数据投资基金领投,老股东跟投。募集资金将投入到云架构师及产品研发团队扩充和
云头条
2022/03/18
4300
嘲笑资本退潮后的共享单车,或在嘲笑资本大潮下我们
ofo一出错,人们就发笑。或许是厌倦了共享单车造成的城市管理乱象,或许是出于对这个声称共享经济的厌倦,ofo只要出现一点负面消息便会引发人们的口诛笔伐。这正是当下的共享单车市场尴尬的地方,一旦资本输血停止,公司便会出现问题,用户便会纷纷倒戈。世态炎凉,或许只有真正参与其中的人们才会知道。回想共享单车大战刚刚兴起的时候,那种尔要战便战的豪气依然历历在目,对于共享单车也没有今天这么多的质疑声音。
孟永辉
2018/12/19
4120
嘲笑资本退潮后的共享单车,或在嘲笑资本大潮下我们
Hive补充之窗口函数
窗口函数 1、hive窗口函数语法 hive中的窗口函数over() ,over()窗口函数的语法结构
Maynor
2021/04/09
1.1K0
非公医院的“心病”与冠脉 AI 的“良药”
“医生提供的服务跟其他的服务业完全不一样,我们面对的是一个个鲜活的生命。如果我把一位患者治好了,挽回的不仅仅是一条生命,更可能是整个家庭的希望。”
AI掘金志
2019/09/26
4690
非公医院的“心病”与冠脉 AI 的“良药”
SQL之窗口函数
窗口函数,也叫OLAP函数(Online Anallytical Processing,联机分析处理),可以对数据库数据进行实时分析处理。 绝大多数情况,sql语句处理数据是行为基本单位,一行一行的对数据操作。窗口函数则是可以对行数据进行分组,将多行数据分成一组,然后进行组间操作或者组内操作。
cultureSun
2023/05/18
3850
SQL之窗口函数
WinForm之窗体应用程序
WinForm之窗体应用程序 基本简单数据库操作(增删改查) 1 using System; 2 using System.Collections.Generic; 3 using System.Windows.Forms; 4 5 namespace DataBaseOperation 6 { 7 static class Program 8 { 9 /// <summary> 10 /// 应用程序的主入口点。 11 /
用户1112962
2018/07/04
1.3K0
tkinter学习系列(二)之窗口的设置
目录 (一)窗体的最小框架 1.说明: 2.源代码: 3.实现效果: (二)窗体的基本设置 1.说明: 2.完整代码: 3.实现效果: (三)窗体的外形设置 1.说明: 2.完整代码: 3.实现效果: (四)窗体的三个方法: 1.获取屏幕的大小 2.获取窗体的大小 3.获取窗体的位置 目录: 1.窗体的最小框架 2.窗体的基本设置 3.窗体的外形设置 (一)窗体的最小框架 1.说明: 需要导入标准库: import tkinter 2.源代码: # 导入模块,并取别名 impor
py3study
2020/01/17
1.1K0
MFC学习之窗口基础
                          WinMain函数  1、句柄(HANDLE):{ 1. 定义:资源的标识 2. 句柄的作用: 操作系统通过句柄来找到对应的资源,从而对这些资源进行管理和操作。 3句柄的分类:(按资源){ 1.图标句柄(HICON) , 2.光标句柄(HCURSOR) ,             3. 窗口句柄(HWND) ,            4.应用程序实列句柄(HINSTANCE). } } 2、Windows应用程序,操作系统,计算机硬件之间的相互关系
Gxjun
2018/03/22
7380
MFC学习之窗口基础
快来,看看spring有多烂-来自jfinaL的嘲笑
脱离任何使用场景的比较,都是傻x行为。但我还是要当一回傻x,就当给新版本jfinal献礼了。
xjjdog
2019/07/10
1.6K1
快来,看看spring有多烂-来自jfinaL的嘲笑
BOM核心——window对象之窗口
浏览器对象模型BOM(Browser,Object,Model)是以window对象为基础的,这个对象代表了浏览器窗口,页面可视区域,它还被复用为Es的全局对象Global,所有的原生类型的构造函数和函数都从一开始就存在于这个对象之上。
大熊G
2022/11/14
9090
企业安全管理的“六脉神剑”
点击标题下「大数据文摘」可快捷关注 当考虑确定计算系统、数据和网络的可用性和完整性控制时,与可考虑潜在机会授权的管理员相比,普通用户拥有更少的特权。系统管理员、执行备份的操作人员、数据库管理员、维修技师甚至帮助台支持人员的运营商,都纷纷在网络中提升权限。为了确保你系统的安全性,还必须考虑可以防止管理员滥用特权的控制。用于管理日常事务以及组织内的数据访问的自动化控制不能保证自己的完整性和可用性,避免过度管理任务的控制。如果控制管理使用权限的控件也不强,那么任何其他的控件也会被削弱。下面一起来看企业安全管理的“
大数据文摘
2018/05/23
8020
5 脉神剑,杀无赦!
分享一个数据,我在 CSDN 上有 19 万多的读者关注了,这个数量应该能排到所有博主里面的 TOP 3(乐观点,自信点),就算是保守估计的话,至少应该是 TOP 10 吧!
沉默王二
2021/04/25
4190
5 脉神剑,杀无赦!
多级时间轮定时器_时间轮与哈希表定时
顾名思义,时间轮就像一个轮子,在转动的时候外界会指向轮子不同的区域,该区域就可以被使用。因此只要将不同时间的定时器按照一定的方法散列到时间轮的不同槽(即时间轮划分的区域)之中,就可以实现在运转到某个槽时,进行判断该定时器是否已经到达运行时间(需要判断是由于有的定时器并非在这一圈就需要运行,可能需要后面几圈才会运行。
全栈程序员站长
2022/11/10
1.2K0
多级时间轮定时器_时间轮与哈希表定时
Lucene 高阶查询的六脉神剑 —— QueryParser
上篇我们介绍了 Lucene 多样的查询模式,每一种都是相互独立的用来解决特定查询目标的 Query 对象。本节我们要将这些查询模式使用 QueryParser 组合起来进行合并查询 —— 用一个文本字符串表达式来表示所有的查询模式。
老钱
2019/09/17
2.6K1
Lucene 高阶查询的六脉神剑 —— QueryParser
flink时间系统系列之窗口函数中的应用分析
在flink中窗口划分可以基于时间、基于数量,我们这里所涉及到的窗口是针对时间类型窗口:processing-time window与event-time window,时间系统在时间窗口应用主要用来注册窗口触发时间点,来决定窗口什么时候开始执行窗口函数。接下来从源码的角度分析窗口是如何使用时间系统的。
Flink实战剖析
2022/04/18
6810
flink时间系统系列之窗口函数中的应用分析
秘籍:微服务设计的六脉神剑
介绍 “微服务”是一种新的软件开发模式,它来源于提高软件开发和管理效率的一系列工程实践。敏捷方法、DevOps文化、PaaS、应用容器、CI/CD文化和技术的广泛采用,使得构建真正的模块化、大规模服务系统成为可能。 什么是微服务? 微服务是一种架构方法,强调将应用拆分成由跨职能团队管理的单目标、松散耦合的多个服务,以满足如今数字时代对软件系统交付和维护速率与质量的要求。 微服务与编程语言、平台、操作系统无关。它将庞大的应用拆分成更小更简单的应用,这些庞大的应用一般都是打成一个软件包。每个应用只需要做好一件
DevOps时代
2018/02/02
8710
秘籍:微服务设计的六脉神剑
打通Python学习的任督二脉
Python的基础知识已经在上周全部更新完成,今天对之前的文章做一个汇总方便大家的查看【多图!加了好多思维导图】同时对有遗漏的知识点也已经做了补充,当然这一部分直接将自己的学习笔记给贴上了,文末加了四篇实战练习和一篇BAT面试题分享。今天更新的次条对LeetCode的1--20题做了汇总,发起了大家一起刷题的活动,后续刷题将不按顺序而是按照具体的知识点。
PM小王
2019/07/02
6850
打通Python学习的任督二脉
【干货】教你打通Git的任督二脉
分布式版本控制系统( Distributed Version Control System,简称 DVCS )。
狼王编程
2021/06/01
4310
【干货】教你打通Git的任督二脉
点击加载更多

相似问题

反应钩形与脉轮

14

如何转换/动画与脉轮-UI?

23

脉轮UI图标

144

脉轮UI,如何使组件与左边对齐?

37

脉轮用户界面图标作为变量

15
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档