首页 > 其他分享 >GXT之旅:第七章:MVC——Navigation,Main和Item区域交互(1)

GXT之旅:第七章:MVC——Navigation,Main和Item区域交互(1)

时间:2022-12-06 11:06:53浏览次数:53  
标签:feed client GXT Item MVC import new com tabItem


(刚干了一个多月的flex项目,一时半会还无法转过神来专注于GXT的东东,有好多东西自己都忘的差不多了。。。。

我得好好屡屡




使用TabPanel显示feeds

之前,我们已经通过RssMainPanel里的 ItemGrid来显示一个feed数据。现在,我们将要使用TabPanel去管理多个TabItem——其中每一个TabItem包含一个 ItemGrid,一个ItemGrid负责显示一个feed数据的多个Items内容。

  • 编辑com.danielvaughan.rssreader.client.components.FeedPanel,新建field——TabPanel
private final TabPanel tabPanel = new TabPanel();
  • 新建一个方法——addTab,传入TabItem参数。设置一些属性,如下:
public void addTab(TabItem tabItem) {
tabItem.setLayout(new FitLayout());
tabItem.setIcon(Resources.ICONS.rss());
tabItem.setScrollMode(Scroll.AUTO);
}
  • 因为我们只是想让一个TabItem负责显示一个feed数据内容,所以当一个TabItem已经拥有feed数据显示到TabPanel的时候,就直接跳转到此TabItem,否则就创建一个新的TabItem
public void addTab(TabItem tabItem) {
tabItem.setLayout(new FitLayout());
tabItem.setIcon(Resources.ICONS.rss());
tabItem.setScrollMode(Scroll.AUTO);

String tabId = tabItem.getId();
TabItem existingTab = tabPanel.findItem(tabId, false);
if (existingTab == null) {
tabPanel.add(tabItem);
tabPanel.setSelection(tabItem);
} else {
tabPanel.setSelection(existingTab);
}
}
  • 重构FeedPanel构造函数:
public FeedPanel() {
setHeading("Main");
setLayout(new FitLayout());
add(tabPanel);
}


连接起来

我们现在几乎已经准备好了所有的UI,现在我们需要将它们连接起来——当用户在Main(FeedPanel)区域选择了某条feed,则在Item(ItemPanel)区域显示出具体的内容。

我们可以根据用户的选择事件操作,将其选择的ModelDate在不同的components之间传递。同样的,也可以通过数据的加载事件,将ModelData在不同的components之间传递。

大致思路如下:

  • 当用户在FeedList选中了一个Feed(link)的时候,一个FeedSelected AppEvent就会搭载其Feed被派发出去。
  • 当FeedSelected AppEvent被派发出来之后,FeedView接收到此事件,然后负责页面跳转到或新建一个ItemGrid来显示Feed

  • 当用户在ItemGrid选中了一个Item的时候,一个ItemSelected AppEvent就会搭载其Item被派发出去。
  • 当ItemSelected AppEvent被派发出来之后,ItemView接收到此事件,然后负责页面使用ItemPanel来显示Item

  • 当用户在TabPanel选中某个tab的时候,一个TabSelected AppEvent就会搭载其Feed被派发出去。
  • 当TabSelectedAppEvent被派发出来之后,FeedList接收到此事件,然后负责联动选中到对应的Feed。

Implements:

  • AppEvents类,新定义三个EventType
public static final EventType FeedSelected = new EventType();
public static final EventType ItemSelected = new EventType();
public static final EventType TabSelected = new EventType();
  • 找到com.danielvaughan.rssreader.client.lists.FeedList类,在其onRender方法里,添加 SelectionChange监听——当用户选择不同的Feed的时候,就会触发SelectionChangedEvent事件,其操作过程,是将传入的selectedItem,派发出去。
package com.danielvaughan.rssreader.client.lists;

import java.util.List;

import com.danielvaughan.rssreader.client.RSSReaderConstants;
import com.danielvaughan.rssreader.client.mvc.events.AppEvents;
import com.danielvaughan.rssreader.client.services.FeedServiceAsync;
import com.danielvaughan.rssreader.shared.model.Feed;
import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.LoadEvent;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.LoadListener;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedListener;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.form.ListField;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class FeedList extends LayoutContainer {

final ListField<BeanModel> feedList = new ListField<BeanModel>();

public FeedList() {
setLayout(new FitLayout());
}

private String getTemplate() {
StringBuilder sb = new StringBuilder();
sb.append("<tpl for=\".\">");
sb.append("<div class='x-combo-list-item'><b>{title}</b> -{description}</div>");
sb.append("</tpl>");
return sb.toString();
}

@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
// 0:从Registry里获得Service
final FeedServiceAsync feedService = (FeedServiceAsync) Registry
.get(RSSReaderConstants.FEED_SERVICE);
// 1:定义proxy在load方法里掉用Serivce里的方法
RpcProxy<List<Feed>> proxy = new RpcProxy<List<Feed>>() {
@Override
protected void load(Object loadConfig,
AsyncCallback<List<Feed>> callback) {
feedService.loadFeedList(false, callback);

}
};
// 2:定义Reader
BeanModelReader reader = new BeanModelReader();
// 3:将proxy和reader传入,定义loader
ListLoader<ListLoadResult<BeanModel>> loader = new BaseListLoader<ListLoadResult<BeanModel>>(
proxy, reader);
// 4:传入loader,生成store,此时还没有load数据
final ListStore<BeanModel> feedStore = new ListStore<BeanModel>(loader);
// 5:将stroe绑定到data-backed component身上
feedList.setStore(feedStore);
feedList.setTemplate(getTemplate());

feedList.addSelectionChangedListener(new SelectionChangedListener<BeanModel>() {
@Override
public void selectionChanged(SelectionChangedEvent<BeanModel> se) {
Feed feed = se.getSelectedItem().getBean();
if (feed != null) {
Dispatcher.forwardEvent(AppEvents.FeedSelected, feed);//关键在这里~~~
}
}
});

// 6:真正的load数据,load成功之后,data-backed component会自动的显示出来。
loader.load();

add(feedList);
}
}


  • 如果想要程序能够对FeedSelected事件作出响应,就必须在关联的Controller注册——FeedController
public FeedController() {
registerEventTypes(AppEvents.Init);

registerEventTypes(AppEvents.FeedSelected);
}


  • 重构ItemGrid的构造函数,增加一个参数为Feed——用来接收FeedSelected事件传递过来的Feed
private final Feed feed;
public ItemGrid(Feed feed) {
setLayout(new FitLayout());
this.feed = feed;
}
  • 继续在ItemGrid类,将onRender方法里面局部变量的grid,提取到方法外面,作为ItemGrid类的属性存在。
private Grid<ModelData> grid;

@Override
protected void onRender(Element parent, int index) {

grid = new Grid<ModelData>(itemStore, columnModel);
}
  • 继续在ItemGrid类的onRender方法里。删除如下局部变量的定义
final String TEST_DATA_FILE = "http://localhost:8888/rss2sample.xml";
  • 取而代之,是使用Feed对象的UUID属性替换之前的TEST_DATA_FILE
RpcProxy<List<Item>> proxy = new RpcProxy<List<Item>>() {
@Override
protected void load(Object loadConfig,
AsyncCallback<List<Item>> callback) {
feedService.loadItems(feed.getUuid(), callback);
}
};


  • 继续在ItemGrid类里,定义一个新的方法——resetSelection,用来重设Grid的选中状态。
public void resetSelection() {
grid.getSelectionModel().deselectAll();
}
  • 在FeedView类,新建一个方法(onFeedSelected)用来响应,接收到的 FeedSelected事件:通过传入的event获得Feed对象;将Feed对象作为参数创建一个ItemGrid;新建TabItem,并设置一些属性,将先前新建的ItemGrid加入到Tabitem里;最后,将tabItem加入到feedPanel里。
private void onFeedSelected(AppEvent event) {
Feed feed = event.getData();
final ItemGrid itemGrid = new ItemGrid(feed);
TabItem tabItem = new TabItem(feed.getTitle());
tabItem.setId(feed.getUuid());
tabItem.setData("feed", feed);
tabItem.add(itemGrid);
tabItem.addListener(Events.Select, new Listener<TabPanelEvent>() {//选中之后的tab会清空item selection
@Override
public void handleEvent(TabPanelEvent be) {
itemGrid.resetSelection();
}
});
tabItem.setClosable(true);
feedPanel.addTab(tabItem);
}
  • 在FeedView类的handleEvent方法里,加入对FeedSelected事件的跳转。到此FeedSelected事件的处理流程完成
@Override
protected void handleEvent(AppEvent event) {
EventType eventType = event.getType();
if (eventType.equals(AppEvents.Init)) {
onInit(event);
}else if (eventType.equals(AppEvents.FeedSelected)) {
onFeedSelected(event);
}
}


  • 在ItemGrid的onRender方法里,添加一个SelectionChange的监听,当用户选择不同的Item的时候,就会触发SelectionChangedEvent事件,其操作过程,是将传入的selectedItem,派发出去。
grid.getSelectionModel().addListener(Events.SelectionChange,
new Listener<SelectionChangedEvent<Item>>() {
@Override
public void handleEvent(SelectionChangedEvent<Item> be) {
Item item = be.getSelectedItem();
if(item!=null)
Dispatcher.forwardEvent(AppEvents.ItemSelected, item);
}
});


  • 同样的,对于ItemSelected方法,我们要在ItemController里注册
public ItemController() {
registerEventTypes(AppEvents.Init);

registerEventTypes(AppEvents.ItemSelected);
}


  • 在ItemView类里,针对ItemSelected AppEvent处理的方法——onItemSelected()
private void onItemSelected(AppEvent event) {
Item item = (Item) event.getData();
itemPanel.displayItem(item);
}
  • 在ItemView类里,handleEvent方法里加入针对ItemSelected事件的处理方法跳转。到此ItemSelected事件的处理流程完成
@Override
protected void handleEvent(AppEvent event) {
EventType eventType = event.getType();
if (eventType.equals(AppEvents.Init)) {
Dispatcher.forwardEvent(new AppEvent(AppEvents.ItemPanelReady,
itemPanel));
} else if (eventType.equals(AppEvents.ItemSelected)) {
onItemSelected(event);
}
}


  • 现在我们还少一个事件处理流程——TabSelected ,但是我们先来看看程序运行效果哈~~~

GXT之旅:第七章:MVC——Navigation,Main和Item区域交互(1)_object



标签:feed,client,GXT,Item,MVC,import,new,com,tabItem
From: https://blog.51cto.com/u_15903664/5915148

相关文章

  • GXT之旅:第六章:Templates(2)——XTemplate(1)
    XTemplateXTemplate比Template更为有用,除了拥有Template相同的功能之外,还具有更多有用的功能——提供使用更多的<tpl>标记来满足自己需要的html显示效果。为了下面例子的引......
  • GXT之旅:第六章:Templates(1)——Template(1)
    第六章:Templates本章我们要了解Templates,以及学习他们是如何方便我们去自定义数据的格式化和显示。我们也会详细了解XTemplates的丰富功能本章,我们会涉及到如下GXt功能集Tem......
  • GXT之旅:第五章:高级Components(6)——TabPanel,Status大概介绍
    TabPanelTabPanel继承Container,作为可以容器,可以负责显示和管理TabItem对象集。TabItem对象集可以方法被add或remove。每一个TabItem都有一个id,用来通过findItem方法来......
  • GXT之旅:第五章:高级Components(2)——Grid的高级应用
    Grid的高级应用之前,我们学习的都是Grid的基本功能。事实上,Grids提供了丰富的功能,下面就让我们了解一下。HeaderGroupConfig假设我们想比较欧洲东部在1950和2000年之间的人......
  • GXT之旅:第五章:高级Components(3)——Paging
    PagingPaging是GXT提供的非常有用的功能。顾名思义,就是分页显示数据,而不是一页显示所有的数据。GXT支持远程和本地的分页:远程分页就是真分页,每次server端返回数据都是数据库......
  • GXT之旅:第七章:MVC——标准的MVC与GXT MVC
    第七章:ModelViewController本章我们要了解GXT的MVC架构,以及学习他们在一个大型的应用系统里是如何系统工作的我们会涉及到如下GXt功能集AppEventEventTypeControllerView......
  • SpringMvc个人理解
    SpringMvc执行流程(1)浏览器提交请求到中央调度器(2)中央调度器直接将请求转给处理器映射器。(3)处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回......
  • mvc,mvp,mvvm 的区别
    这三者都是框架模式,它们设计的目标都是为了解决Model和View的耦合问题。MVC模式出现较早主要应用在后端,如SpringMVC、ASP.NETMVC等,在前端领域的早期也有应用,如Backbone......
  • extjs4,spring mvc3上传文件
    本文讲解下extjs4结合springmvc3的注解完成上传文件的例子。1页面文件  <!--ExtJSFiles--><linkrel="stylesheet"type="text/css......
  • springmvc注册fastJson报错
    原因:依赖版本问题这是我原本引入的依赖,版本是1.2.24<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId......