ein 'SWT.VIRTUAL' TableViewer mit mehreren Spalten

Dr$arez

Grünschnabel
Einfache Frage - Schwierige Antwort!!

Ich erzeuge eine virtuelle Tabelle a la:
Code:
TableViewer v = new TableViewer(shell, SWT.VIRTUAL);
. Dieser Viewer wird von einem ContentProvider gefüttert, der eigentlich nur das Interface
Code:
ILazyContentProvider
mit der Methode
Code:
void updateElement(int index)
implementieren muss. Bei jedem Aufruf der Update-Funktion aus dem Viewer heraus, wird der Viewer über ein Handle bei index aktualisiert:
Code:
viewer.replace(model.getObject(index), index);
.

Damit lassen sich meines Erachtens aber nur eindimensionale Tabellen erzeugen (also eine Spalte mit gegebenem Zeilen'index'. Jetzt meine Frage: Wie implementiert man eine Tabelle mit mehreren Spalten als Virtual? (Ich will die an die Tabelle gelieferten Daten erst bei Abfrage liefern).

Hut ab vor dem, der dazu eine lösende Antwort weiß oder sich damit auskennt.
 
Hallo,

schau mal hier:
Java:
package de.tutorials;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ILazyContentProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.ApplicationWindow;
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.FillLayout;
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.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableColumn;

public class JFaceTableViewerExample extends ApplicationWindow {
    TableViewer tableViewer;

    Model model;

    public JFaceTableViewerExample(Shell parentShell) {
        super(parentShell);
    }

    @Override
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setSize(640, 480);
    }

    protected Control createContents(Composite parent) {
        Composite composite = new Composite(parent, SWT.NULL);
        GridLayout gridLayout = new GridLayout(1, false);
        composite.setLayout(gridLayout);
        String[] columnNames = new String[] { "COLUMN_A", "COLUMN_B",
                "COLUMN_C" };

        tableViewer = new TableViewer(composite, SWT.VIRTUAL);
        tableViewer.setColumnProperties(columnNames);
        TableColumn tableColumn = new TableColumn(tableViewer.getTable(),
                SWT.NULL);
        tableColumn.setText(columnNames[0]);
        tableColumn.setWidth(100);

        tableColumn = new TableColumn(tableViewer.getTable(), SWT.NULL);
        tableColumn.setText(columnNames[1]);
        tableColumn.setWidth(100);

        tableColumn = new TableColumn(tableViewer.getTable(), SWT.NULL);
        tableColumn.setText(columnNames[2]);
        tableColumn.setWidth(100);
        tableViewer.setContentProvider(createContentProvider());
        tableViewer.setLabelProvider(createLabelProvider());

        tableViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
        tableViewer.getTable().setLinesVisible(true);
        tableViewer.getTable().setHeaderVisible(true);
        tableViewer.setUseHashlookup(true);

        model = (Model) createInput();

        tableViewer.setInput(model);
        tableViewer.setItemCount(model.getData().size());

        Button btnUpdate = new Button(composite, SWT.PUSH);
        btnUpdate.setText("update");
        btnUpdate.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                long time = System.currentTimeMillis();
                model.getData().add(
                        new Object[] { "A_" + time, "B_" + time, null });
                tableViewer.setItemCount(model.getData().size());
            }
        });
        return composite;
    }

    static class Model {
        List<Object[]> data = new CopyOnWriteArrayList<Object[]>();

        public List<Object[]> getData() {
            return data;
        }
    }

    private Object createInput() {
        Model model = new Model();
        model.data.add(new Object[] { "A_0", "B_0", null });
        return model;
    }

    class TableLabelProvider implements ITableLabelProvider {
        public Image getColumnImage(Object element, int columnIndex) {
            return null;
        }

        public String getColumnText(Object element, int columnIndex) {
            return ((Object[]) element)[columnIndex].toString();
        }

        public void addListener(ILabelProviderListener listener) {
        }

        public void dispose() {
        }

        public boolean isLabelProperty(Object element, String property) {
            return false;
        }

        public void removeListener(ILabelProviderListener listener) {
        }
    }

    private IBaseLabelProvider createLabelProvider() {
        return new TableLabelProvider();
    }

    class ContentProvider implements ILazyContentProvider,
            IStructuredContentProvider {

        Model model;

        public Object[] getElements(Object inputElement) {
            return this.model.data.toArray();
        }

        public void dispose() {

        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            System.out.println("inputChanged");
            this.model = (Model) newInput;
        }

        public void updateElement(int index) {
            Object[] row = model.getData().get(index);
            row[2] = row[0] + " " + row[1];
            tableViewer.replace(row, index);
        }

    }

    private IContentProvider createContentProvider() {
        return new ContentProvider();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        JFaceTableViewerExample example = new JFaceTableViewerExample(shell);
        example.setBlockOnOpen(true);
        shell.pack();
        example.open();
    }

}

Gruß Tom
 
"Darimont schrieb... und es wurde Licht."

Ich habe mal wieder viel zu kompliziert gedacht, aber richtig: in dem punkt unterscheidet sich ja der TableViewer nicht von virtual und non-virtual. aber danke für die präziese antwort - bei dir lernt man immer dazu. ich wäre zum beispiel nie auf die verwendung der threadsicheren CopyBeforeWriteArrayList() gekommen.
Das ist ein toller Gedanke. Habe noch nie vorher gehört von. Kenne nur das Konzept aus einigen Eclipse-Codes (zum Beispiel die modifizierenden Methoden der ListenerList.class von org.eclipxe.? )

Danke!

Hier noch einmal die Zusammenfassung meines dadurch gelösten Problems:

Code:
1. i instantiated a new virtual TableViewer
2. i added (for example 2) TableColumns to the TableViewer and set their width
3. i set my own TableLabelProvider to the TableViewer in which 'getColumnText' i returned following: "return ((Object[]) element)[columnIndex].toString();"
3. thus i can set a ILazyTableProvider to my TableViewer implementing the 'updateElement'-method e.g. like this: "viewer.replace(new Object[] { model.getCol(0).getObject(index), model.getCol(1).getObject(index) }, index);"
 

Neue Beiträge

Zurück