如何将ComplexPanel与GWT ActivityManager一起使用

如何将ComplexPanel与GWT ActivityManager一起使用,gwt,gwt-2.3,Gwt,Gwt 2.3,我试图修改GWT2.1HellomVP示例代码,以使用更复杂的UI。(由于双链接限制,我不允许提供链接) 我的问题是ActivityManager.setDisplay只接受实现AcceptsOneWidget的对象。LayoutPanel和其他ComplexPanel不实现AcceptsOneWidget。示例代码改用SimplePanel。但我似乎无法在SimplePanel中嵌套复杂的小部件(它们不显示) 我发现了一些关于这个问题的讨论: 人们建议解决方案是创建我想要的ComplexP

我试图修改GWT2.1HellomVP示例代码,以使用更复杂的UI。(由于双链接限制,我不允许提供链接)

我的问题是ActivityManager.setDisplay只接受实现AcceptsOneWidget的对象。LayoutPanel和其他ComplexPanel不实现AcceptsOneWidget。示例代码改用SimplePanel。但我似乎无法在SimplePanel中嵌套复杂的小部件(它们不显示)

我发现了一些关于这个问题的讨论:

人们建议解决方案是创建我想要的ComplexPanel的子类,该子类实现AcceptsOneWidget接口。像这样:

public class PanelForView extends LayoutPanel implements AcceptsOneWidget { 
     IsWidget myWidget = null; 

    @Override 
     public void setWidget(IsWidget w) { 
         if (myWidget != w)  { 
             if (myWidget != null) { 
                 remove(myWidget); 
             } 

            if (w != null) { 
                 add(w); 
             } 

            myWidget = w; 
         } 
     } 
} 
public class HelloMVP implements EntryPoint { 
    private Place defaultPlace = new HelloPlace("World!"); 
//  private SimplePanel appWidget = new SimplePanel(); // Replace this with PanelForView 
    private PanelForView appWidget = new PanelForView(); // This compiles but doesn't work. 
//  private SimpleLayoutPanel appWidget = new SimpleLayoutPanel(); // This doesn't work either. 

    public void onModuleLoad() { 
        // Create ClientFactory using deferred binding so we can replace with different 
        // impls in gwt.xml 
        ClientFactory clientFactory = GWT.create(ClientFactory.class); 
        EventBus eventBus = clientFactory.getEventBus(); 
        PlaceController placeController = clientFactory.getPlaceController(); 

        // Start ActivityManager for the main widget with our ActivityMapper 
        ActivityMapper activityMapper = new AppActivityMapper(clientFactory); 
        ActivityManager activityManager = new ActivityManager(activityMapper, eventBus); 
        activityManager.setDisplay(appWidget); 

        // Start PlaceHistoryHandler with our PlaceHistoryMapper 
        AppPlaceHistoryMapper historyMapper= GWT.create(AppPlaceHistoryMapper.class); 
        PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper); 
        historyHandler.register(placeController, eventBus, defaultPlace); 

        RootPanel.get().add(appWidget); 
        // Goes to place represented on URL or default place 
        historyHandler.handleCurrentHistory(); 
    } 
} 
这听起来不错,但似乎对我不起作用。可能是因为我使用的是GWT2.3,而不是2.1或2.2。在我的入口点中,我希望用我的新PanelForView类简单地替换SimplePanel,并让应用程序像以前一样运行。像这样:

public class PanelForView extends LayoutPanel implements AcceptsOneWidget { 
     IsWidget myWidget = null; 

    @Override 
     public void setWidget(IsWidget w) { 
         if (myWidget != w)  { 
             if (myWidget != null) { 
                 remove(myWidget); 
             } 

            if (w != null) { 
                 add(w); 
             } 

            myWidget = w; 
         } 
     } 
} 
public class HelloMVP implements EntryPoint { 
    private Place defaultPlace = new HelloPlace("World!"); 
//  private SimplePanel appWidget = new SimplePanel(); // Replace this with PanelForView 
    private PanelForView appWidget = new PanelForView(); // This compiles but doesn't work. 
//  private SimpleLayoutPanel appWidget = new SimpleLayoutPanel(); // This doesn't work either. 

    public void onModuleLoad() { 
        // Create ClientFactory using deferred binding so we can replace with different 
        // impls in gwt.xml 
        ClientFactory clientFactory = GWT.create(ClientFactory.class); 
        EventBus eventBus = clientFactory.getEventBus(); 
        PlaceController placeController = clientFactory.getPlaceController(); 

        // Start ActivityManager for the main widget with our ActivityMapper 
        ActivityMapper activityMapper = new AppActivityMapper(clientFactory); 
        ActivityManager activityManager = new ActivityManager(activityMapper, eventBus); 
        activityManager.setDisplay(appWidget); 

        // Start PlaceHistoryHandler with our PlaceHistoryMapper 
        AppPlaceHistoryMapper historyMapper= GWT.create(AppPlaceHistoryMapper.class); 
        PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper); 
        historyHandler.register(placeController, eventBus, defaultPlace); 

        RootPanel.get().add(appWidget); 
        // Goes to place represented on URL or default place 
        historyHandler.handleCurrentHistory(); 
    } 
} 
这编译得很好,但当我运行它时,我看到的只是一个空白屏幕。初始化ComplexPanel需要做些额外的事情吗?我只是误解了什么吗?我尝试过添加小部件并调用setSize,但没有效果。这是我的第一个GWT项目

谢谢你抽出时间


Corey

您应该能够轻松地使用SimplePanel(或ImplementAcceptsOneWidget的复合子类)。实现这一点的最佳方法是考虑包含的小部件。您可以在SimplePanel的一个小部件区域中添加:HTMLPanel、FlowPanel、VerticalPanel等

但是,一旦执行此操作,您就改变了ActivityMapper/AcceptsOneWidget/SimplePanel的预期用途

您可以通过以下方式创建更复杂的ui:

添加另一个ActivityMapper(具有不同的UI区域-SimplePanel-应该在不同的地方更改)或添加小部件区域(不会在不同的地方更改)

或*

让您的活动控制更复杂的视图(将ActivityMapper.setDisplay小部件保持为SimplePanel,然后将活动设置为HTMLPanel、VerticalPanel等)

一个非常流行的实现是保留SimplePanel作为ActivityMapper的内容区域。然后使用UiBinder(HTMLPanel作为顶级元素)

我们可以将UiBinder称为“视图”,它可以有许多区域

view.getTopArea() - SimplePanel, view.getLeft() - FlowPanel, view.getNameArea - Anchor/InlineHTML
所有这些不同的元素都被包装到视图中,视图可以是一个复合视图

然后,在你的

activity.start(AcceptsOneWidget panel){
 panel.setWidget(view);//insert your complex view into the SimplePanel view
  ...
}

好的,所以当我遇到这个问题时,我只是在试验示例应用程序附带的非常简单的UI

我还尝试保留SimplePanel,让活动返回一个由标签和图像组成的HeaderPanel(Ashton回答中提到的第二种方法)。我以为这没用。我在博客和论坛上看到的评论似乎表明这是行不通的。但一旦我开始用DockPanel和嵌套的TabPanel等构建UI,所有的东西都开始正常显示。我不知道为什么。我想这可能是我代码中的一个bug。但我在路上。我不想回去准确地诊断出哪里出了问题。:)

谢谢你们的建议,伙计们


Corey

使用RootLayoutPanel而不是RootPanel

尝试删除if语句
if(myWidget!=w)
谢谢Ashton,你提到的第二种方法是我最初想到的。但我也要考虑第一个问题。你能详细说明为什么要这样做吗?