Как синхронизировать прокрутку между двумя таблицами в vaadin 7?

У меня есть две таблицы в vaadin. Один из них как таблица mainTable. Другим является ScrollTable freezeTable. Мне нужна синхронизация прокрутки между двумя таблицами. Если я буду прокручивать mainTable по вертикали, замораживание таблицы должно прокручиваться так же, но в случае горизонтальной прокрутки мне не нужна синхронизация прокрутки. Я получил некоторую идею от форума vaadin, как показано ниже. Но я не могу продолжить из-за какого-то устаревшего метода.

В MyViewPage.java я добавляю эти две таблицы как

addComponent(loadTables());
public HorizontalSplitPanel loadTables(){
    final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
    Table mainTable = new Table();
    ScrollTable freezeTable=new ScrollTable();
    freezeTable.setDependentTable( mainTable );
    freezeTable.setWidth( "300px" );
    mainTable.setWidth( "800px" );
    freezeTable.setContainerDataSource(myContainer);
    freezeTable.setVisibleColumns(viscol);
    freezeTable.setColumnHeaders(vishead);
    freezeTable.setPageLength(15);
    mainTable.setContainerDataSource(myAnotherContainer);
    mainTable.setVisibleColumns(viscolmain);
    mainTable.setColumnHeaders(visheadmain);
    mainTable.setPageLength(15);
    splitPanel.setFirstComponent(freezeTable);
    splitPanel.setSecondComponent(mainTable);
    return splitPanel;
}

Класс ScrollTable выглядит так.

ScrollTable.java

package com.abhiram.app.myproject.freezetable;

import com.vaadin.data.Container;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.shared.ui.Connect;

import com.vaadin.ui.Table;

@SuppressWarnings("serial")
public class ScrollTable extends Table{
private Table mainTable;

public ScrollTable()
 {
   super();
 }
public void setDependentTable( Table mainTable)
 {
   this.mainTable= mainTable;
 }

@Override
public void paintContent( PaintTarget target ) throws PaintException
  {

    target.addAttribute( "scrollPane", this );
    if ( table != null ) target.addAttribute( "dependentTable", mainTable);
    super.paintContent( target );
  }
}

Я создал еще один класс VMyScrollTable и расширил VScrollTable следующим образом.

VMyScrollTable.java

package com.abhiram.app.myproject.freezetable.client.ui;

import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.abhiram.app.myproject.freezetable.ScrollTable;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.UIDL;
import com.vaadin.client.ui.FocusableScrollPanel;
import com.vaadin.client.ui.VScrollTable;
import com.vaadin.shared.ui.Connect;
@Connect(com.abhiram.app.myproject.freezetable.ScrollTable.class)
public class VMyScrollTable extends VScrollTable{
public VMyScrollTable()
 {
   super();
 }

@Override
public void updateFromUIDL( final UIDL uidl, final ApplicationConnection client )
 {
  super.updateFromUIDL(uidl,client );
  final String tableId = uidl.getStringAttribute( "dependentTable" );
  if ( tableId == null )
     return;
  String id = uidl.getStringAttribute( "scrollPane" );

  VScrollTable scrollPane = (VScrollTable) client.getPaintable(id);
  final FocusableScrollPanel scrollBody = (FocusableScrollPanel) scrollPane.getWidget(1);
  scrollBody.addScrollHandler( new ScrollHandler()
   {
     @Override
     public void onScroll( ScrollEvent event )
      {
        VMyScrollTable.this.onScroll( event );
        VScrollTable dependentPane = (VScrollTable)  client.getPaintable(tableId );
        FocusableScrollPanel scrollToBeBody = (FocusableScrollPanel) dependentPane.getWidget( 1 );
        scrollToBeBody.setScrollPosition( scrollBody.getScrollPosition() );
      }
     } );
   }
}

Здесь проблема заключается в том, что класс VScrollTable не имеет метода, такого как updateFromUIDL(...), а ApplicationConnection не имеет метода, такого как getPaintable(String). Я не могу продолжить из-за этого. Пожалуйста, помогите мне, как это сделать.


person Mina    schedule 31.05.2014    source источник


Ответы (1)


Вы на правильном пути, но, похоже, вы путаете Widget с ComponentConnector. Вот рабочая версия, измененная из вашего кода:

ScrollTable.java – идентично вашему

public class ScrollTable extends Table {
    private Table mainTable;

    public void setDependentTable(Table mainTable) {
        this.mainTable = mainTable;
    }

    @Override
    public void paintContent(PaintTarget target) throws PaintException {

        target.addAttribute("scrollPane", this);
        if (mainTable != null) {
            target.addAttribute("dependentTable", mainTable);
        }
        super.paintContent(target);
    }
}

ScrollTableConnector.java — это класс соединителя, который находится на клиенте между Widget и сервером.

@Connect(ScrollTable.class)
public class ScrollTableConnector extends TableConnector implements
        ScrollHandler {

    private VScrollTable dependentPane = null;

    @Override
    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
        super.updateFromUIDL(uidl, client);
        String tableId = uidl.getStringAttribute("dependentTable");
        if (tableId == null) {
            return;
        }
        if (dependentPane == null) {
            FocusableScrollPanel scrollBody = (FocusableScrollPanel) getWidget()
                    .getWidget(1);
            scrollBody.addScrollHandler(this);
        }
        dependentPane = ((TableConnector) client.getConnector(tableId, 0))
                .getWidget();
    }

    @Override
    public void onScroll(ScrollEvent event) {
        FocusableScrollPanel scrollBody = (FocusableScrollPanel) getWidget()
                .getWidget(1);
        FocusableScrollPanel scrollToBeBody = (FocusableScrollPanel) dependentPane
                .getWidget(1);
        scrollToBeBody.setScrollPosition(scrollBody.getScrollPosition());
    }
}

...вот и все. Нет необходимости изменять виджет; вместо этого мы напрямую повторно используем VScrollTable. И ваш исходный тестовый пользовательский интерфейс должен работать как есть, поскольку на стороне сервера ничего не изменилось.

Теперь ScrollTableConnector, будучи ComponentConnector, является кодом на стороне клиента и должен быть помещен в ваш клиентский пакет, то есть исходный путь вашего набора виджетов. Например, если ваш файл *.gwt.xml находится в пакете com.example.foo, ScrollTableConnector должен находиться в пакете com.example.foo.client или в одном из его подпакетов. Таким образом, компилятор набора виджетов будет знать, где его искать.

И, наконец, не забудьте перекомпилировать свой набор виджетов. Если вы используете плагин Vaadin Eclipse, просто нажмите кнопку Compile Widgetset. Если вы используете Maven, запустите mvn vaadin:compile.

person jupenur    schedule 02.06.2014
comment
Привет Jupenur, Спасибо за ваш ответ. Но это не работает. Я даю sysout внутри этих трех переопределенных методов. Метод PaintContent выполняется в первый раз при загрузке страницы. Методы updateFromUIDL() и onScroll() не выполняются. - person Mina; 02.06.2014
comment
Он по-прежнему отображает обе таблицы на стороне клиента? Вы не забыли перекомпилировать набор виджетов? Ваш ScrollTableConnector находится в исходном пути набора виджетов? - person jupenur; 02.06.2014
comment
Я не создаю набор виджетов. Я использую этот проект. В netbeans я только создаю свой проект и развертываю его на сервере jboss liferay. Пожалуйста, проверьте ссылку ниже. https://www.dropbox.com/s/4qqjp81vgrjlaoh/myproject.zip @юпенур - person Mina; 03.06.2014
comment
Вы должны переместить ScrollTableConnector в пакет com.abhiram.app.client, а затем перекомпилировать набор виджетов. Я обновил свой ответ информацией о том, как это сделать. - person jupenur; 03.06.2014
comment
Я переместил ScrollTableConnector в com.abhiram.app.client пакет. Я обновил набор виджетов, используя vaadin:update-widgetset. Он успешно строится. Но когда я компилирую с использованием vaadin:compile, он показывает ошибку как `[ОШИБКА] Ошибки в 'файле:/E:/New%20folder/myproject-parent/myproject/target/classes/com/abhiram/app/client/ScrollTableConnector. java` [ОШИБКА] Строка 19: com.abhiram.app.ScrollTable не может быть преобразована в тип [ОШИБКА] Строка 19: Class‹ScrollTable› не может быть преобразована в тип [ОШИБКА] Прерывание компиляции из-за ошибок в некоторых входных файлах` @jupenur - person Mina; 04.06.2014
comment
Я предполагаю, что компилятор набора виджетов ищет класс из каталога target и по той или иной причине его там нет. Однако это всего лишь предположение. Попробуйте перекомпилировать проект в IDE, а затем снова запустить mvn vaadin:compile. - person jupenur; 04.06.2014
comment
На самом деле я использую IDE netbeans. В первый раз он не распознавал vaadin:compile. Потом я что-то изменил в pom.xml. После компиляции с использованием compiler:compile также отображается ошибка, о которой я упоминал в предыдущем комментарии. См. ссылку https://www.dropbox.com/s/ouo2k9nc3ls8cac/myproject-parent.zip для всего моего родительского проекта с модулем. Спасибо, @jupenur - person Mina; 04.06.2014
comment
Добавление этого в конфигурацию vaadin-maven-plugin помогло: <persistentunitcachedir>${project.build.directory}</persistentunitcachedir> - person jupenur; 04.06.2014
comment
Та же ошибка возникает после добавления <persistentunitcachedir>${project.build.directory}</persistentunitcachedir> в конфигурацию vaadin-maven-plugin @jupenur - person Mina; 04.06.2014
comment
После изменения запустите mvn clean compiler:compile vaadin:compile - person jupenur; 04.06.2014
comment
Теперь компилируем правильно. Но синхронизированная прокрутка не работает. @jupenur - person Mina; 05.06.2014
comment
Действительно? Я проверил это даже с проектом, на который вы мне указали, и у меня все работает нормально. Что именно происходит? Вы видите что-нибудь странное в окне отладки Vaadin? А может я просто как-то неправильно понял ваш вопрос? - person jupenur; 05.06.2014
comment
Вот что у меня есть: goo.gl/Fe9eWA Если на вашем компьютере это выглядит иначе, значит, что-то не так с строить. - person jupenur; 05.06.2014
comment
Теперь он работает нормально. Мой последний проект: https://www.dropbox.com/s/rz1ghabbp4ispj5/freezetable.zip. Но одна проблема. Мне не нужна полоса прокрутки в случае зависимой таблицы. Я скрываю это, написав css как overflow: hidden. Оба стола имеют одинаковую высоту. Когда я полностью прокрутил вниз, в конце произошло совпадение строки. Потому что на правом столе есть горизонтальная полоса прокрутки, а на левом нет. Если у меня есть ячейка большей высоты в любой таблице, возникает несоответствие строк. Пожалуйста, есть ли какое-нибудь решение для этого..@jupenur - person Mina; 11.06.2014
comment
Вместо этого попробуйте overflow-y: hidden; таким образом, горизонтальная полоса прокрутки остается видимой. - person jupenur; 11.06.2014
comment
Мне нужно, чтобы обе полосы прокрутки были невидимыми. Другое дело, что если я сделаю overflow-y:hidden и у меня не будет больше столбца в левой таблице для полосы прокрутки, горизонтальная полоса прокрутки все равно останется невидимой. @jupenur - person Mina; 11.06.2014
comment
Привет Юпенур, я решил проблему. Спасибо большое за вашу помощь. Я хочу задать еще одно сомнение. Как и метод onScroll в интерфейсе ScrollHandler, есть ли что-нибудь для column resize handler?? @jupenur - person Mina; 13.06.2014
comment
Это становится слишком не по теме. :) Почему бы вам вместо этого не задать новый вопрос и не включить более подробную информацию о том, чего вы пытаетесь достичь. У меня есть vaadin в избранном, поэтому я обязательно увижу его и отвечу, если никто не ответит. - person jupenur; 13.06.2014