I need to display an unknown quantity of tabs each with an unknown quantity of graphs (Google Visualizations). I have created “Tab” and “Graph” classes and Tab contains an ArrayList.
TabWrappers extends FlexTable and is currently empty. It’s a place holder at the moment, but the behavior does not change if I use FlexTable rather than TabWrapper.
The code below, minus the section that adds Tab2 works perfectly for creating 1 tab populated with graphs. When adding the 2nd tab both tabs are displayed and named correctly but neither have graphs.
public class SomeClass {
...
DataTable data = response.getDataTable();
DataView result;
Options options = createOptions();
ArrayList<Tab> displayTab = new ArrayList<Tab>();
Tab t;
ArrayList<Graph> graphList = new ArrayList<Graph>();
Graph g;
t = new Tab();
g = new Graph();
result = DataView.create(data);
result.setRows(new int[]{0, 2, 4, 6});
g.setGraphType(new PieChart(result, options));
graphList.add(g);
g = new Graph();
result = DataView.create(data);
result.setRows(new int[]{1, 3, 5, 7});
g.setGraphType(new PieChart(result, options));
graphList.add(g);
g = new Graph();
result = DataView.create(data);
g.setGraphType(new PieChart(result, options));
graphList.add(g);
t.setTabName("Tab1");
t.setGraphs(graphList);
displayTab.add(t);
// Add a 2nd tab
t = new Tab();
t.setTabName("Tab2");
t.setGraphs(graphList);
displayTab.add(t);
TabWrapper tabWrapper;
for (Tab tX : displayTab){
int row = 0, col = 0, maxCol = 2;
tabWrapper = new TabWrapper();
for (Graph gX : tX.getGraphs()) {
col = tX.getGraphs().indexOf(gX) - (row * maxCol);
tabWrapper.setWidget(row, col, gX.getGraphType().asWidget());
if (++col == maxCol) {
row++;
}
}
tabPanel.add(tabWrapper, tX.getTabName());
}
...
}
When you use tabs in GWT, the panels held in each tab seem to be lazy loaded and aren’t completely set up until the user clicks on each tab.
In particular, the tab containers will have zero widths and heights (the error logs will probably be giving an error about containers having zero width) so the graph drawing will fail and leave an empty space.
What you need to do (and is probably good practice anyway) is to lazy load the contents of the tabs too so that the graph is loaded only when the tab is fully set up. This can be done by removing the call the t.setGraphs(…) and adding a selection handler that does it instead:
so that graphs are added and drawn only when the tab is selected.
You’ll probably also want to call
to force a selection of the first tab after the selection handler is in place.
I had the same issues that you describe and this resolved it.