Community
Participate
Working Groups
I have a virtual table that performs actions on checked rows after a button is clicked. To figure out what rows to act on the button's selection listener calls the CheckboxTableViewer's getCheckedElements method. Invoking this method causes all of the rows that were not originally visible (the ones that you need to scroll to get to) disappear. Here is the getCheckedElements method from CheckboxTableViewer public Object[] getCheckedElements() { TableItem[] children = getTable().getItems(); ArrayList v = new ArrayList(children.length); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; if (item.getChecked()) v.add(item.getData()); } return v.toArray(); } If you comment out the getChecked() line of code the table gets drawn correctly. I have included the source code for this test case. Here is how you can reproduce it. 1. Launch TestCheckBoxTableViewer 2. Scroll to the bottom. You should be able to see all the rows. 3. Click on the button 4. Scroll to the bottom. You will see allot of blank rows. 5. Comment out the call to item.getChecked in MyCheckboxTableViewer's getCheckedElements method. Rerun the test case. This time it works. Here is the test case source code: import java.util.ArrayList; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.List; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.deferred.AbstractConcurrentModel; import org.eclipse.jface.viewers.deferred.DeferredContentProvider; import org.eclipse.jface.viewers.deferred.IConcurrentModelListener; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; /** * * @author cgustafson * */ public class TestCheckBoxTableViewer { MyCheckBoxTableViewer tableViewer; public TestCheckBoxTableViewer(Composite parent){ createContents(parent); } private void createContents(Composite parent){ parent.setLayout(new GridLayout()); Button button = new Button(parent,SWT.PUSH); button.setText("Click here to see rows disapear"); Table table = new Table(parent,SWT.VIRTUAL | SWT.V_SCROLL | SWT.CHECK); table.setHeaderVisible(true); table.setLinesVisible(true); GridData gd = new GridData(); gd.grabExcessVerticalSpace = true; gd.verticalAlignment = SWT.FILL; gd.grabExcessHorizontalSpace = true; gd.horizontalAlignment = SWT.FILL; gd.heightHint = 500; table.setLayoutData(gd); TableColumn checkCol = new TableColumn(table, SWT.LEFT); checkCol.setWidth(20); TableColumn dateCol = new TableColumn(table, SWT.LEFT); dateCol.setText("Date"); dateCol.setWidth(200); tableViewer = new MyCheckBoxTableViewer(table); tableViewer.setContentProvider(new TestContentProvider(new TestComparator(true))); tableViewer.setLabelProvider(new TestLabelProvider()); int size = 90; Date data[] = new Date[size]; Calendar cal = Calendar.getInstance(); for (int i=0;i < size;i++){ cal.add(Calendar.DAY_OF_MONTH,1); data[i] = cal.getTime(); } TestModel model = new TestModel(); model.set(data); tableViewer.setInput(model); tableViewer.refresh(); button.addSelectionListener(new SelectionAdapter(){ public void widgetSelected(SelectionEvent e) { tableViewer.getCheckedElements(); } }); } class TestContentProvider extends DeferredContentProvider{ public void dispose() { } public TestContentProvider(Comparator sorter){ super(sorter); } } class TestLabelProvider implements ITableLabelProvider{ private List listeners = new ArrayList(); public String getColumnText(Object element, int columnIndex){ if (columnIndex == 1){ return element.toString(); } else return null; } public Image getColumnImage(Object element, int columnIndex){ return null; } public void dispose(){ } public void removeListener(ILabelProviderListener listener){ listeners.remove(listener); } public boolean isLabelProperty(Object element, String property){ return false; } public void addListener(ILabelProviderListener listener){ listeners.add(listener); } } class TestComparator implements Comparator{ boolean ascending; TestComparator(boolean ascending){ this.ascending = ascending; } public int compare(Object o1, Object o2) { Date lhs = (Date) o1; Date rhs = (Date) o2; int answer; if (ascending){ answer = lhs.compareTo(rhs); } else{ answer = rhs.compareTo(lhs); } return answer; } } public class TestModel extends AbstractConcurrentModel { private ArrayList data = new ArrayList(); public Object[] getElements() { return data.toArray(); } /** * Sets the contents to the given array of elements * * @param newContents new contents of this set */ public void set(Object[] newContents) { data.clear(); for (int i = 0;i<newContents.length;i++){ data.add(newContents[i]); } IConcurrentModelListener[] listeners = getListeners(); for (int i = 0; i < listeners.length; i++) { IConcurrentModelListener listener = listeners [i]; listener.setContents(getElements()); } } /** * Empties the set */ public void clear() { Object[] removed = getElements(); data.clear(); fireRemove(removed); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.deferred.IConcurrentContentProvider#requestUpdate (org.eclipse.jface.viewers.deferred.IConcurrentContentProviderListener) */ public void requestUpdate(IConcurrentModelListener listener) { listener.setContents(getElements()); } public int size(){ return data.size(); } } public class MyCheckBoxTableViewer extends CheckboxTableViewer{ public MyCheckBoxTableViewer(Table table) { super(table); } // I copied this from CheckboxTableViewer public Object[] getCheckedElements() { TableItem[] children = getTable().getItems(); ArrayList v = new ArrayList(children.length); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; // Comment out the following line to see the test case work. if (item.getChecked()) v.add(item.getData()); } return v.toArray(); } } public static void main(String[] args){ System.out.println("Starting table"); Display display = new Display(); Shell shell = new Shell(display); shell.setText("Testing Stuff"); TestCheckBoxTableViewer table = new TestCheckBoxTableViewer (shell); shell.pack(); shell.open(); while (!shell.isDisposed()){ if (!display.readAndDispatch()){ display.sleep(); } } display.dispose(); } } Thanks Chad
I also noticed the same behavior while looping through the rows of the table. For example: int total = table.getItemCount(); for (int i=0;i<total;i++){ System.out.println(table.getItem(i).getText(1)); }
This is likely the same problem as Bug 92769. I have made a version of this that uses a standard content provider (TestCheckBoxTableViewerSimple) that does not have this issue. I will attach a project that has all of the examples in this Bug and Bug 92769.
Created attachment 21326 [details] Zip with Chad and Tods examples Here is a zip file with Chads two examples for this and Bug 92769. The versions with Simple in the title do not use the DeferredContentProvider and do not have the issues either bug is reporting.
Any chance this will ever be fixed?
(In reply to comment #4) > Any chance this will ever be fixed? It has a pretty low priority, but is marked as helpwanted. See http://wiki.eclipse.org/Platform_UI/How_to_Contribute
Seems like a pretty big issue... To me deferredcontentprovider + SWT.VIRTUAL doesn't work.
DeferredContentProvider needs a fair amount of work and is not in use within the SDK for that reason.
Are there any other work arounds to populate the table in a background thread?
(In reply to comment #8) > Are there any other work arounds to populate the table in a background thread? Peter, can you recommend anything?
Hitesh is now responsible for watching bugs in the [Viewers] component area.
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug. If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie.