JFace Data Binding

overflow

Mitglied
Hi liebe Leute,

ich habe ein Problem, bei dem ich einfach nicht weiter komme.
Ich verwende einen TableViewer, den ich mit daten aus einem Modell füttere, was auch passt. Hinzufügen bzw. entfernen kann man auch ganz praktisch, soweit so gut.
Allerdings muss, um Änderungen an den Datensätzen an sich im Table sichtbar zu machen, ein LabelObserver eingesetzt werden, welcher diese Änderungen erfasst und weitergibt.

Allerdings hab ichs bisher nicht hingebracht, auch nur irgendeine Änderung zu erfassen, drum wende ich mich an euch, in der Hoffnung, ihr könnt mir hier etwas klarheit verschaffen.

Habe allen Code, der in diese Richtung ging wieder entfernt, damit es wenigstens ein wenig übersichtlicher wird. Stand unten ist eben eine Tabelle, welche mit Initialdaten gefüllt wird und wo man hinzufügen/entfernen kann. Es solln aber eben noch Modelländerungen angezeigt werden.

Zusatzinfo: Vorlage war zu gutem Teil das Tutorial von Lars Vogel

--- Klasse Person: ---

Java:
public class Person extends AbstractModelObject{

	private int ID;

	public enum Anrede {
		Herr, Frau
	};

	private Anrede Anrede;
	private String Vorname, Nachname, Adresse, Ort, Telefon, Email, Handy;
	private int Plz;
	private Date Gebdat;

	public Person() {
		this.ID = -1;
	}

	public Person(int _ID, Anrede _Anrede, String _Vorname, String _Nachname,
			String _Adresse, String _Ort, String _Telefon, String _Email,
			String _Handy, int _Plz, Date _Gebdat) {

		this.ID = _ID;
		this.Anrede = _Anrede;
		this.Vorname = _Vorname;
		this.Nachname = _Nachname;
		this.Adresse = _Adresse;
		this.Ort = _Ort;
		this.Plz = _Plz;
		this.Handy = _Handy;
		this.Telefon = _Telefon;
		this.Email = _Email;
		this.Gebdat = _Gebdat;
	}

	/* Methoden */

	public int getAlter() {
		Calendar GebTag = Calendar.getInstance();
		GebTag.setTime(this.Gebdat);
		Calendar today = Calendar.getInstance();
		int age = today.get(Calendar.YEAR) - GebTag.get(Calendar.YEAR);
		if (today.get(Calendar.DAY_OF_YEAR) < GebTag.get(Calendar.DAY_OF_YEAR))
			age--;
		return age;
	}
	
	public String toString() {
		if (this.Anrede != null)
			return this.Anrede.toString() + " " + this.Vorname + " " + this.Nachname;
		else
			return this.Vorname + " " + this.Nachname;
	}

	/* Getter und Setter */

	public int getID() {
		return this.ID;
	}

	public void setID(int iD) {
		firePropertyChange("ID", this.ID, this.ID = iD);
	}

	public Anrede getAnrede() {
		return this.Anrede;
	}

	public void setAnrede(Anrede anrede) {
		firePropertyChange("anrede", this.Anrede, this.Anrede = anrede);
	}

	public String getVorname() {
		return this.Vorname;
	}

	public void setVorname(String vorname) {
		firePropertyChange("vorname", this.Vorname,	this.Vorname = vorname);
	}

	public String getNachname() {
		return this.Nachname;
	}

	public void setNachname(String nachname) {
		firePropertyChange("nachname", this.Nachname, this.Nachname = nachname);
	}
	
	[...]
	
}

Java:
public abstract class AbstractModelObject {
	
   private final PropertyChangeSupport m_propertyChangeSupport = new PropertyChangeSupport(this);

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      m_propertyChangeSupport.addPropertyChangeListener(listener);
   }
   public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
      m_propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
   }
   public void removePropertyChangeListener(PropertyChangeListener listener) {
      m_propertyChangeSupport.removePropertyChangeListener(listener);
   }
   public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
      m_propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
   }
   public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
      m_propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
   }
}

--- Mitglied erweitert Person ---
Java:
public enum ModelProvider {
	INSTANCE;

	private List<Mitglied> Mitglieder;

	private ModelProvider() {
		Mitglieder = new ArrayList<Mitglied>();
		
		/* Datenbankzugriff um die user auszulesen */
		[...]
	}
		
	public List<Mitglied> getMitglieder() {
		return Mitglieder;
	}
	
	public void printAll() {
		for ( Mitglied m : Mitglieder )	{
		  System.out.println(m.getAnrede() + " " + m.getVorname() + " " + m.getNachname());
		}
	}
}

--- View mit Tabelle ---
Java:
	private MitgliederComparator comparator;
	private TableViewer viewer;
	private WritableList input;

	// Icons
	private static final Image HAT_PARTNER = Activator.getImageDescriptor(
			"icons/partner.png").createImage();

	public void createPartControl(Composite parent) {
		
		GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		
		Label searchLabel = new Label(parent, SWT.NONE);
		searchLabel.setText("Search: ");
		final Text searchText = new Text(parent, SWT.BORDER | SWT.SEARCH);
		searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL	| GridData.HORIZONTAL_ALIGN_FILL));
	
		//createViewer(parent);
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
		createColumns(parent, viewer);
		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);
		
		// Sortierer fürn Table
		comparator = new MitgliederComparator();
		viewer.setComparator(comparator);

		// Bindes
		input = new WritableList(ModelProvider.INSTANCE.getMitglieder(),
				Mitglied.class);
		//viewer.setInput(input);
		ViewerSupport.bind(
				viewer,
				input,
				BeanProperties.values(new String[] { "anrede", "vorname",
						"nachname", "geburtsdatum" }));
		
		
		// Testfunktionen - Löschen
		Button delete = new Button(parent, SWT.PUSH);
		delete.setText("Delete");
		delete.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (!viewer.getSelection().isEmpty()) {
					IStructuredSelection selection = (IStructuredSelection) viewer
							.getSelection();
					Mitglied m = (Mitglied) selection.getFirstElement();
					input.remove(m);
				}
			}
		});
		// Hinzufügen
		Button add = new Button(parent, SWT.PUSH);
		add.setText("Add");
		add.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				Mitglied m = new Mitglied();
				m.setVorname("Test1");
				m.setNachname("Test2");
				input.add(m);
			}
		});
		//Werte tauschen
		Button change = new Button(parent, SWT.PUSH);
		change.setText("Switch First / Lastname");
		change.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (!viewer.getSelection().isEmpty()) {
					IStructuredSelection selection = (IStructuredSelection) viewer
							.getSelection();
					Mitglied m = (Mitglied) selection.getFirstElement();
					System.out.println(m.getVorname() + " - " + m.getNachname());
					String temp = m.getNachname();
					m.setNachname(m.getVorname());
					m.setVorname(temp);
				}
			}
		});
		//Modell ausgeben
		Button print = new Button(parent, SWT.PUSH);
		print.setText("Print");
		print.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				ModelProvider.INSTANCE.printAll();
			}
		});

	}

	public TableViewer getViewer() {
		return viewer;
	}

	// This will create the columns for the table
	private void createColumns(final Composite parent, final TableViewer viewer) {
        
		// Anrede
		TableViewerColumn col = createTableViewerColumn("Anrede", 50, 0);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				if (m.getAnrede() == Anrede.Herr)
					return "Herr";
				else
					return "Frau";
			}
		});

		// Vorname
		col = createTableViewerColumn("Vorname", 100, 1);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return m.getVorname();
			}
		});

		// Nachname
		col = createTableViewerColumn("Nachname", 100, 2);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return m.getNachname();
			}
		});

		// GebTag
		col = createTableViewerColumn("Gebutsdatum", 75, 3);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				Format format = new SimpleDateFormat("dd.MM.yyyy");
				return format.format(m.getGebdat()).toString();
			}
		});

		// Partner
		col = createTableViewerColumn("Partner", 50, 4);
		col.setLabelProvider(new CenterImageLabelProvider() {

			@Override
			public Image getImage(Object element) {
				if (((Mitglied) element).hatPartner()) {
					return HAT_PARTNER;
				} else {
					return null;
				}
			}
		});

		// Adresse
		col = createTableViewerColumn("Adresse", 150, 5);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return m.getAdresse();
			}
		});

		// PLZ
		col = createTableViewerColumn("PLZ", 50, 6);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return String.valueOf(m.getPlz());
			}
		});

		// Ort
		col = createTableViewerColumn("Ort", 75, 7);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return m.getOrt();
			}
		});

		// Telefon
		col = createTableViewerColumn("Telefon", 100, 8);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return m.getTelefon();
			}
		});

		// Handy
		col = createTableViewerColumn("Handynummer", 100, 9);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return m.getHandy();
			}
		});

		// Mail
		col = createTableViewerColumn("EMail", 125, 10);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Mitglied m = (Mitglied) element;
				return m.getEmail();
			}
		});
	}

	private TableViewerColumn createTableViewerColumn(String title, int bound,
			final int colNumber) {
		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
				SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		column.addSelectionListener(getSelectionAdapter(column, colNumber));
		return viewerColumn;

	}

	private SelectionAdapter getSelectionAdapter(final TableColumn column,
			final int index) {
		SelectionAdapter selectionAdapter = new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				comparator.setColumn(index);
				int dir = comparator.getDirection();
				viewer.getTable().setSortDirection(dir);
				viewer.getTable().setSortColumn(column);
				viewer.refresh();
			}
		};
		return selectionAdapter;
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}

	/* *
	 * Erweiterter ImageLabelProvider, der die Labels zentriert
	 */

	private abstract class CenterImageLabelProvider extends
			OwnerDrawLabelProvider {

		protected void measure(Event event, Object element) {
		}

		protected void paint(Event event, Object element) {

			Image img = getImage(element);

			if (img != null) {
				Rectangle bounds = ((TableItem) event.item)
						.getBounds(event.index);
				Rectangle imgBounds = img.getBounds();
				bounds.width /= 2;
				bounds.width -= imgBounds.width / 2;
				bounds.height /= 2;
				bounds.height -= imgBounds.height / 2;

				int x = bounds.width > 0 ? bounds.x + bounds.width : bounds.x;
				int y = bounds.height > 0 ? bounds.y + bounds.height : bounds.y;

				event.gc.drawImage(img, x, y);
			}
		}

		protected abstract Image getImage(Object element);

	}
}


Vielen Dank fürs Lesen und ich hoffe, jemand kann mir helfen :)
lg
M
 
Zuletzt bearbeitet von einem Moderator:

Wildcard

Top Contributor
Dein LabelProvider muss ein Listener auf dem Modell sein um einen refresh anstoßen zu können.
Mein Tipp, lass dir dein Modell mit EMF erzeugen. Das Modell wird dadurch besser, du sparst dir das ganze PropertyChange Zeug, das Databinding wird einfacher und mächtiger und die LabelProvider und ContentProvider bekommst du gratis dazu (die sich auch automatisch aktualisieren).

Dann musst du dir auch um Undo/Redo und Transaktionen keine Gedanken mehr machen, EMF kann das alles.
 

overflow

Mitglied
Hi Wildcard,

danke für den Tipp, hab eh schon mehrfach über EMF gelesen, nur wollte ich nicht in zu viele neue Bereiche zugleich vordringen. Werde es mir aber direkt mal ansehen.
Hast du eventuell mal eine schöne Seite mit einem Tutorial/Anleitung oder dergleichen gefunden, welche du empfehlen kannst? Wenn nicht find ich sicher auch was ;)

Danke und lg
M
 

overflow

Mitglied
Hi Wildcard,

Danke mal für die Seite, die hatte ich eh schon gefunden. Habs auch schon mal nachgebaut, das prob is nur: der gute Lars erklärt recht wenig, er gibt nur Anleitungen, was zu amchen ist... für was ich da jetzt ein Edit und einen Editor undw as weiss ich noch alles für Code generier weiss ich trotzdem ned :)

Ich nehme an, ein schönen Tutorial, wo dann zb auch das Databinding an ein JFace control erklärt wird, gibtz ned, oder? Ich hätte zumindest nichts gefunden.

So, wies auf der einen Seite war, schien es mir auf jeden fall etwas zu kompliziert, zumal ich eben auch ned die Feinheiten gesehn hab (also eben DB, Validierungen, conversion, etc.)

Danke auf jeden Fall für dein bemühen,

lg
 

Wildcard

Top Contributor
Danke mal für die Seite, die hatte ich eh schon gefunden. Habs auch schon mal nachgebaut, das prob is nur: der gute Lars erklärt recht wenig, er gibt nur Anleitungen, was zu amchen ist... für was ich da jetzt ein Edit und einen Editor undw as weiss ich noch alles für Code generier weiss ich trotzdem ned
Der EMF Editor kann dir 4 Dinge generieren:
Model: Das Datenmodell
Edit: UI Gluecode zB für Content- und LabelProvider
Editor: ein funktionsfähiger CRUD Editor für Eclipse
Test: JUnit Test Stubs für dein Modell
Ich nehme an, ein schönen Tutorial, wo dann zb auch das Databinding an ein JFace control erklärt wird, gibtz ned, oder? Ich hätte zumindest nichts gefunden.
Gibt es auch, müsste ich aber erst suchen. Das Databinding ist sehr einfach. Funktioniert wie normales JFace Databinding, nur das du dir das PropertyChange Zeug sparen kannst. Stattdessen verwendest du EMFProperties als einstiegspunkt, oder EMFEditProperties, wenn automatisch Undo/Redo unterstützt werden soll.

So, wies auf der einen Seite war, schien es mir auf jeden fall etwas zu kompliziert, zumal ich eben auch ned die Feinheiten gesehn hab (also eben DB, Validierungen, conversion, etc.)
Glaub mir, es ist nicht kompliziert, nur am Anfang viel neues. DB, Validierung, conversion, was genau möchtest du wissen?
 

overflow

Mitglied
Hey Wildcard,

vielen Dank nochmal für deine Anmerkung! Ich hab mir jetzt noch ein paar Seiten rausgesucht, wo ich mich einlesen werde. Detailfragen stell ich dann eventuell später, muss mich erst vernünftig einarbeiten.
Danke auf jeden Fall für deine Hilfe :)

lg
 
G

Gast2

Gast
Gibt es auch, müsste ich aber erst suchen. Das Databinding ist sehr einfach. Funktioniert wie normales JFace Databinding, nur das du dir das PropertyChange Zeug sparen kannst. Stattdessen verwendest du EMFProperties als einstiegspunkt, oder EMFEditProperties, wenn automatisch Undo/Redo unterstützt werden soll.

Es gibt doch auch schon ein JFace Databinding, dass das alles ohne das PropertyChange zeugs hinbekommt.

5. JFace Data Binding with POJOs
 
G

Gast2

Gast
Das geht aber nur in eine Richtung, UI -> Model.

Nochmal zu dem Thema das geht doch auch in beide Richtungen =).

Java:
public class Person{

String firstname;

//getter setter
Beispiel
Java:
bindingContext.bindValue(SWTObservables.observeText(textField,
                           SWT.Modify), PojoObservables.observeValue(myPerson,
                           "firstName"), null,null);
 

Ähnliche Java Themen


Oben