Refreshing a Table on a not visible TabSheet.Tab causes mainwindow to scrol

Hi,

We have a form where there are two tables on a TabSheet, and we refresh these tables periodically. This form is a vertical layout, so it’s scrollable. If user scrolls to the bottom of the form, clicks into tbl1 on tab1, and then clicks tab2 (so tbl1 will be invisible), refreshing tbl1 will cause mainWindow to scroll to top. Since refresh interval is relatively low, this jumping means form is unusable after selecting a row in any table.

Here’s a simple Application to demonstrate this behaviour. (Please note that in our project we use we a javascript timer which calls to server side periodically, in this example I changed it to ProgressIndicator. Also note I’ve removed some steps from table refreshing code, like refreshing values in datasource, preserving row selection with getValue/setValue - these were not necessary to reproduce the problem).


public class TabletestApplication extends Application {


  @Override
  public void init() {
    Window mainWindow = new Window("Tabletest Application");
    VerticalLayout root = new VerticalLayout();

    final Table tbl1 = createTable();
    tbl1.setSizeFull();
    VerticalLayout tbl1Layout = new VerticalLayout();
    tbl1Layout.setSizeFull();
    tbl1Layout.addComponent(tbl1);
    final Table tbl2 = createTable();
    tbl2.setSizeFull();
    VerticalLayout tbl2Layout = new VerticalLayout();
    tbl2Layout.setSizeFull();
    tbl2Layout.addComponent(tbl2);
    TabSheet tabSheet = new TabSheet();
    tabSheet.addTab(tbl1Layout, "tab1");
    tabSheet.addTab(tbl2Layout, "tab2");
    tabSheet.setHeight("1200px");
    tabSheet.setWidth("100%");
    root.addComponent(tabSheet);

    mainWindow.addComponent(root);
    setMainWindow(mainWindow);

    // Refresh timer based on ProgressIndicator example from Book of Vaadin (version 6)
    final ProgressIndicator refreshTimer = new ProgressIndicator(new Float(0.0));
    refreshTimer.setPollingInterval(500);
    root.addComponent(refreshTimer);

    // these fields are not really useable because of jumpy behaviour
    root.addComponent(new TextField("Business value 1"));
    root.addComponent(new TextField("Business value 2"));
    root.addComponent(new TextField("Business value 3"));

    // Thread to refresh tables after some time
    class RefreshTablesThread extends Thread {

      public void run() {
        double current = 0.0;
        while (true) {
          try {
            sleep(50);
          } catch (InterruptedException e) {
          }
          current += 0.01;
          if (current > 1.0)
            refreshTimer.setValue(new Float(1.0));
          else
            refreshTimer.setValue(new Float(current));

          if (current > 1.2) {
            System.out.println("timer finished, refreshing");
            tbl1.requestRepaint();
            tbl1.refreshRowCache();
            tbl2.requestRepaint();
            tbl2.refreshRowCache();
            refreshTimer.setValue(new Float(0.0));
            // start next refresh timer
            new RefreshTablesThread().start();
            break;
          }
        }
      }
    }
    // start first timer
    new RefreshTablesThread().start();
  }

  private Table createTable() {

    Table tbl = new Table("Table");
    Container ds = new IndexedContainer();
    tbl.setImmediate(true);
    tbl.setMultiSelect(true);
    tbl.setSelectable(true);
    ds.addContainerProperty("id", Integer.class, null);
    ds.addContainerProperty("col1", String.class, null);
    ds.addContainerProperty("col2", String.class, null);
    ds.addContainerProperty("col3", String.class, null);
    for (int i = 0; i < 1000; i++) {
      Item item = ds.addItem(i);
      item.getItemProperty("id").setValue(i);
      item.getItemProperty("col1").setValue("col1_" + i);
      item.getItemProperty("col2").setValue("col2_" + i);
      item.getItemProperty("col3").setValue("col3_" + i);
    }
    tbl.setContainerDataSource(ds);
    return tbl;
  }

}

Steps to recreate error:

  • start app
  • make sure main window has a scroll bar (Business value 1 is not visible when scrolled to top)
  • select a row in tbl1 on tab1
  • select tab2
  • scroll down to Business value 1
  • wait for progress indicator to finish
  • when it’s finished, mainwindow will scroll to top.

Does anyone has any idea how can we get rid of this scolling behaviour in Vaadin6? I ported this sample to Vaadin7 and it works as expected, but unfortunately we cannot use Vaadin7 yet,

Thanks,
Attila

I’ve created a ticket with this problem: http://dev.vaadin.com/ticket/12749

Hi,

can’t say if it would fix anything, but when you touch any vaadin components from an external thread, you should synchronize the actions on the application instance, e.g.:

synchronized(currentApplicationInstance) {
// Update your table from here
}

Hi,

Thanks, I’ve tried but it didn’t help. Btw I borrowed code from
https://vaadin.com/book/vaadin6/-/page/components.progressindicator.html
where WorkThread doesn’t sync appInstance when updates indicator.

Yes, the example in the book is broken and I have created a ticket (a long time ago) to fix it but that hasn’t happened yet.