GXT (Ext-GWT): проблемы с компоновкой с ContentPanel

У меня есть ContentPanel, который подходит для всего окна. Он имеет topComponent, виджет в центре и bottomComponent.

Я получаю проблемы с макетом, когда пытаюсь добавить виджеты в topComponent после того, как ContentPanel был отображен один раз:

public void onModuleLoad() {

    final Viewport viewport = new Viewport();
    viewport.setLayout(new FitLayout());

    final ContentPanel contentPanel = new ContentPanel(new FitLayout());
    contentPanel.setHeaderVisible(false);

    final LayoutContainer topContainer = new LayoutContainer(
            new FlowLayout());

    final Button buttonOne = new Button("Top:One");
    topContainer.add(buttonOne);

    contentPanel.setTopComponent(topContainer);
    contentPanel.add(new Button("Center"));
    contentPanel.setBottomComponent(new Button("Bottom"));

    viewport.add(contentPanel);
    RootPanel.get().add(viewport);

    // Later, add a second button to the topComponent ...
    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
        @Override
        public void execute() {
            final Button buttonTwo = new Button("Top:Two");
            topContainer.add(buttonTwo); // Doesn't show up at first.

            topContainer.layout(); // Now, buttonTwo shows up. But we have
                            // a new problem: the "Bottom" button disappears...

            contentPanel.layout(true); // This doesn't do anything, BTW.
        }
    });
}

одна интересная вещь об этом заключается в том, что макет исправляет себя, как только я изменяю размер окна браузера. Что я могу сделать, чтобы сделать его повторно макет правильно сразу (я попытался добавить несколько layout() звонки и т. д. в нескольких местах и комбинациях, но не повезло.)

(Я использую GWT 2.1.1 с GXT 2.2.1.)

3 ответов


это происходит потому, что при добавлении другого компонента в FlowLayout он изменяется, тем самым увеличивая свою собственную высоту, которая толкает Нижний компонент ниже видимой области. В коде нет ничего, что сжимает центральный компонент, так что Нижний компонент остается на своем исходном месте.

еще одна вещь заключается в том, что вы используете FitLayout для contentPanel, который содержит 3 компонента, FitLayout используется для контейнеров только с одним компонентом внутри, который предполагалось заполнить его родителя.

необходимо учитывать следующее:

1) Используйте RowLayout, который позволяет гораздо лучше контролировать, как компоненты должны быть выложены

2) решите, на каком компоненте вы хотите разместить вертикальную полосу прокрутки, так как вы добавляете компоненты динамически.

для вашего текущего требования достаточно следующего кода:

public void onModuleLoad() {
       final Viewport viewport = new Viewport();
       viewport.setLayout(new FitLayout());

//     final ContentPanel contentPanel = new ContentPanel(new FlowLayout());
//     contentPanel.setHeaderVisible(false);

        final LayoutContainer topContainer = new LayoutContainer(
                new FlowLayout());

        final Button buttonOne = new Button("Top:One");
        topContainer.add(buttonOne);
//    contentPanel.setTopComponent(topContainer);
        final LayoutContainer centerPanel = new LayoutContainer(new FitLayout());

        centerPanel.add(new Button("Center"));
//    contentPanel.add(centerPanel);
        final LayoutContainer botPanel = new LayoutContainer(new FlowLayout());
        botPanel.add(new Button("Bottom"));
//      contentPanel.setBottomComponent(botPanel);

        final ContentPanel panel = new ContentPanel();  
        panel.setHeaderVisible(false);  
        panel.setLayout(new RowLayout(Orientation.VERTICAL));    


        panel.add(topContainer, new RowData(1, -1, new Margins(4)));  
        panel.add(centerPanel, new RowData(1, 1, new Margins(0, 4, 0, 4)));  
        panel.add(botPanel, new RowData(1, -1, new Margins(4)));  

        viewport.add(panel, new FlowData(10));  


        RootPanel.get().add(viewport);

        // Later, add a second button to the topComponent ...
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
            @Override
            public void execute() {
                final Button buttonTwo = new Button("Top:Two");
                topContainer.add(buttonTwo); // Doesn't show up at first.
                panel.layout(true);
            }
        });
}

это происходит потому, что onRender событие topComponent вызывается в этом заявлении:

contentPanel.setTopComponent(topContainer);

затем, позже, вы добавляете компонент:topContainer.add(buttonTwo);. При изменении размера окна onRender событие запускается,и кнопка, которую вы добавили, появляется. Решение вашей проблемы включает в себя запуск onRender событие topContainer.

к сожалению, onRender защищен и поэтому вы не можете назвать его непосредственно: http://dev.sencha.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/LayoutContainer.html#onRender%28com.google.gwt.user.client.Element,%20int%29

вы захотите использовать fireEvent чтобы вызвать это программно вместо ручного изменения размера окна: http://dev.sencha.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/Component.html#fireEvent%28com.extjs.gxt.ui.client.event.EventType%29


Как только браузер завершит рендеринг виджета, он больше не будет рендерить этот компонент, чтобы сделать это снова, мы можем использовать contentPanel.макет() или contentPanel.макет(правда) он повторно отображает виджеты в соответствии с новым макетом.