Заполнение огромной таблицы в приложении SWT/JFace RCP
Как вы собираетесь отображать огромное количество строк в таблице SWT? Огромное - это что-то выше 20 тыс. Строк, 20 столбцов. Не спрашивайте меня, почему мне нужно показать много данных, это не главное. Дело в том, как заставить его работать как можно быстрее, чтобы конечный пользователь не уставал ждать. Каждая строка отображает экземпляр какого-либо объекта, а столбцы - его свойства (некоторые). Я думал использовать шаблон содержания JFace/label provider, но боюсь, что он будет еще медленнее, чем попадание в таблицу непосредственно с данными. Вот как это делается:
Display.getDefault().asyncExec(new Runnable() {
public void run() {
List<MyObject> objects = model.getViewData();
for(MyObject object: objects){
TableItem item = new TableItem(table, SWT.NULL);
item.setImage(0, img1);
item.setBackground(color1);
item.setText(0, object.getProperty0());
item.setText(1, object.getProperty1());
item.setText(2, object.getProperty2());
.....
}
});
Рисунок 20k записей на моем компьютере занимает около 20 секунд.
Самая большая проблема с производительностью, которую я видел в Windows, вызвана невероятным количеством собственных оконных сообщений, отправленных SWT, когда создается новый элемент таблицы и заполняется текстом. Я нашел для этого большое обходное решение - скрыть таблицу перед заполнением, а затем показать ее, когда закончите. Просто вызывая table.setVisible(false) перед циклом и table.setVisible(true) после того, как цикл делает чудеса - скорость увеличивается шесть-семь раз!
Я хотел бы ускорить его еще больше.
Что ты предлагаешь? Кроме того, мне интересно, как этот трюк, скрывающий виджет, будет работать на не-windows-реализациях SWT (aka Linux)?
Ответы
Ответ 1
SWT может сделать это за вас. Когда вы используете флаг SWT.VIRTUAL, элементы создаются только при прокрутке в представлении. Вот как это сделать:
- Создайте таблицу со стилем SWT.VIRTUAL
- Установить количество строк, используя таблицу # setItemCount()
- Добавить слушателя SWT.SetData, который заполняет таблицы по запросу.
Здесь фрагмент кода:
public static void main( String[] args ) {
Display display = new Display();
Shell shell = new Shell( display );
shell.setLayout( new FillLayout() );
final Table table = new Table( shell, SWT.VIRTUAL );
table.setItemCount( 10000 );
table.addListener( SWT.SetData, new Listener() {
public void handleEvent( Event event ) {
TableItem item = (TableItem)event.item;
item.setText( "Item " + table.indexOf( item ) );
}
} );
shell.setSize( 300, 500 );
shell.open();
while( !shell.isDisposed() ) {
if( !display.readAndDispatch() ) {
display.sleep();
}
}
display.dispose();
}
Ответ 2
Вы хотите делать ленивую загрузку на дисплее таблицы. В принципе, вы сохраняете все эти объекты вне экрана в памяти, а затем создаете только несколько фактических строк таблицы GUI. Когда пользователь прокручивает, вы повторно визуализируете эти строки с объектами в этом месте прокрутки.
См. в этой статье (EDIT: oops Я имел в виду этой статьи) для примера JFace.
Ответ 3
1 - используйте setText (String []) вместо setText (int, String) один вызов вместо нескольких.
2 - используйте myTable.setRedraw(false) before и myTable.setRedraw(true) после процесса, чтобы остановить все операции перерисовки во время загрузки данных.
это проще и может улучшить производительность!
Удачи.
на моей стороне, используя это, я загружаю 2500 строк из 20 столбцов менее чем за 300 мс..... на стандартном сегодня ПК.