I have a ContentPanel that fits the entire window. It has a topComponent, a widget in the center, and a bottomComponent.
I'm getting layout problems, when I try to add widgets to the topComponent after the ContentPanel has been rendered once:
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.
}
});
}
One interesting thing about this is, that the layout corrects itself, as soon as I resize the browser window. What can I do to make it re-layout correctly immediately (I've tried adding several layout()
calls etc. in several places and combinations, but haven't had any luck so far.)
(I'm using GWT 2.1.1 with GXT 2.2.1.)
This is happening because when you add another component to a FlowLayout it resizes, thus increasing its own height, which pushes the bottom component below the visible area. There is nothing in the code which shrinks the center component, such that the bottom component stays in its original place.
One more thing is that you are using FitLayout for contentPanel which contains 3 components, a FitLayout is used for Containers with only one component inside, which is supposed to fill out its parent.
You need to consider the following:
1) Use RowLayout, which allows a much better control on how components should be laid out
2) Decide on which component are you willing to place a vertical scroll bar, since you are adding components dynamically.
For your current requirement the following code should suffice:
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);
}
});
}
This is happening because the onRender
event of topComponent
is being invoked in this statement:
contentPanel.setTopComponent(topContainer);
Then, later, you are adding a component: topContainer.add(buttonTwo);
. When you resize the window, the onRender
event is triggered, and the button you added shows up. The solution to your problem involves triggering the onRender
event for topContainer
.
Unfortunately, onRender
is protected and therefore you cannot call it directly:
http://dev.sencha.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/LayoutContainer.html#onRender%28com.google.gwt.user.client.Element,%20int%29
You will want to use fireEvent
to trigger this programmatically instead of manually resizing the window:
http://dev.sencha.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/Component.html#fireEvent%28com.extjs.gxt.ui.client.event.EventType%29
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With