JFace Databinding Radiobuttons

In diesem Beitrag geht es um die Verwendung der JFace Datenbindung mit zwei Radiobuttons.

Radiobuttons Databinding

Wie in der obigen Abbildung zu sehen werden zwei Button als Radiobuttons eingefügt (m_yesButton, m_noButton), ein Label welches den Wert des Members rbstate und ein Button zum direkten Setzen des Modellwertes rbstate.

Das Snippet wurde unter Eclipse (Oxygen Release (4.7.0)) erstellt und kann dort als Java Anwendung gestartet werden. Klickt man einen Radiobutton an, wird das Modell auf diesen Wert gesetzt. Steht rbstate auf YES, kann man mit dem Button „Auf No“ rbstate auf „NO“ setzen. Dann wird über die Datenbindung die Auswahl der Radiobuttons automatisch aktualisiert.

In der Methode iniDataBinding wird die Datenbindung vorgenommen. Dabei werden zunächst Observablen für die Selektion der Radiobuttons erstellt (Z130, Z132). Dazu wird eine SelectObservableValue  Observable erstellt, die mit addOption die Observablen für die Radiobuttons erhält (Z 135-Z 138). Dann wird die Observable für die Variable rbstate erzeugt (Z 140) und schliesslich selbige mit der SelectObservableValue gebunden(Z 143).

Die Observable für rbstate wird dann noch mit der Widget Observablen für den Label gebunden(Z 147).

Im Modell liegt die Modellklasse als Bean vor! D.h. es liegen zu den Variablen Getter und Setter vor.

 

/*******************************************************************************
 * Copyright (c) 2017 Günter Stubbe.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Das Programm zeigt die Datenbindung zweier Radiobuttons, die in beide 
 * Richtungen funktioniert: Das Schalten der Buttons ändert das Modell, die 
 * Änderung im Modell bewirkt die Aktualisierung des GUI
 ******************************************************************************/

package org.eclipse.jface.examples.databinding.snippets;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.SelectObservableValue;
import org.eclipse.jface.databinding.swt.DisplayRealm;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.examples.databinding.snippets.SnippetRadioButton1.YesNoModel.RESPONSE;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class SnippetRadioButton1 {
	protected Shell shell;

	private Button m_yesButton;
	private Button m_noButton;

	private Text m_labelActValue;

	public YesNoModel yesNoModel;
	// DataBindingContext bindingContext;

	/**
	 * Anwendung starten
	 *
	 */
	public static void main(String[] args) {
		try {
			SnippetRadioButton1 window = new SnippetRadioButton1();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Hauptfenster anzeigen
	 */
	public void open() {
		final Display display = Display.getDefault();
		Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
			public void run() {
				createContents();
				shell.open();
				shell.layout();
				while (!shell.isDisposed()) {
					if (!display.readAndDispatch())
						display.sleep();
				}
			}
		});
	}

	/* Oberflächenelemente erzeugen */
	protected void createContents() {
		shell = new Shell();
		shell.setSize(300, 200);
		shell.setText("SnippetRadioButton1.java");
		final GridLayout gridLayout = new GridLayout();
		gridLayout.makeColumnsEqualWidth = true;
		gridLayout.numColumns = 4;
		// shell.setLayout(new FillLayout());
		shell.setLayout(gridLayout);
		Composite radioButtonGroupContainer = new Composite(shell, SWT.NONE);
		radioButtonGroupContainer.setLayout(new GridLayout());
		Label question = new Label(radioButtonGroupContainer, SWT.NONE);
		question.setText("TestFrage");

		m_yesButton = new Button(radioButtonGroupContainer, SWT.RADIO);
		m_yesButton.setText("Yes");
		m_noButton = new Button(radioButtonGroupContainer, SWT.RADIO);
		m_noButton.setText("No");
		m_noButton.setSelection(true);

		// hier wird angezeigt, was gerade ausgewählt wurde
		m_labelActValue = new Text(shell, SWT.NONE);

		// Die Daten aus dem Model
		yesNoModel = new YesNoModel();

		// Ein Button zum manipulieren des Modells: Hier wird der rbState
		// auf NO gesetzt - stehen die Radiobuttons auf YES schalten sie
		// automatisch auf NO um.
		Button setMBtn = new Button(shell, SWT.PUSH);
		setMBtn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				// Modell auf NO setzen
				// Die folgende Zeile ist zwingend so erforderlich! Die
				// übernächste Zeile, die jetzt auskommentiert ist,
				// funktionierte nicht!!! Mit der auskommentierten Zuweisung
				// wird das PropertyChange Event nicht ausgelöst und das
				// GUI nicht automatisch aktualisiert.
				SnippetRadioButton1.this.yesNoModel.setRbstate(RESPONSE.NO);
				// SnippetRadioButton1.this.yesNoModel.rbstate = RESPONSE.NO;
				System.out.println(SnippetRadioButton1.this.yesNoModel.rbstate);
			}
		});
		setMBtn.setText("Auf NO");
		iniDataBinding();
	}

	void iniDataBinding() {
		DataBindingContext bindingContext = new DataBindingContext();

		IObservableValue yesBtnSelection = WidgetProperties.selection()
				.observe(m_yesButton);
		IObservableValue noBtnSelection = WidgetProperties.selection()
				.observe(m_noButton);

		SelectObservableValue featureRepoPolicyObservable = new SelectObservableValue(
				YesNoModel.RESPONSE.class);
		featureRepoPolicyObservable.addOption(RESPONSE.YES, yesBtnSelection);
		featureRepoPolicyObservable.addOption(RESPONSE.NO, noBtnSelection);

		IObservableValue obsModelLabel = BeanProperties.value("rbstate")
				.observe(yesNoModel);

		bindingContext.bindValue(featureRepoPolicyObservable, obsModelLabel);

		IObservableValue obsLabel = WidgetProperties.text(SWT.Modify)
				.observe(m_labelActValue);
		bindingContext.bindValue(obsLabel, obsModelLabel, null, null);
	}

	// Ab hier folgen die Klassen für die Modeldaten
	// Minimal JavaBeans support
	public static abstract class AbstractModelObject {
		private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
				this);

		public void addPropertyChangeListener(PropertyChangeListener listener) {
			propertyChangeSupport.addPropertyChangeListener(listener);
		}

		public void addPropertyChangeListener(String propertyName,
				PropertyChangeListener listener) {
			propertyChangeSupport.addPropertyChangeListener(propertyName,
					listener);
		}

		public void removePropertyChangeListener(
				PropertyChangeListener listener) {
			propertyChangeSupport.removePropertyChangeListener(listener);
		}

		public void removePropertyChangeListener(String propertyName,
				PropertyChangeListener listener) {
			propertyChangeSupport.removePropertyChangeListener(propertyName,
					listener);
		}

		protected void firePropertyChange(String propertyName, Object oldValue,
				Object newValue) {
			propertyChangeSupport.firePropertyChange(propertyName, oldValue,
					newValue);
		}
	}

	// Model
	public static class YesNoModel extends AbstractModelObject {

		private RESPONSE rbstate;
		private String cstext;

		public static enum RESPONSE {
			YES, NO
		}

		public YesNoModel() {
			rbstate = RESPONSE.YES;
			cstext = "";
		}

		public String getCstext() {
			return cstext;
		}

		public void setCstext(String cstext) {
			this.firePropertyChange("cstext", this.cstext,
					this.cstext = cstext);
		}

		public RESPONSE getRbstate() {
			return rbstate;
		}

		public void setRbstate(RESPONSE rbstate) {

			this.firePropertyChange("rbstate", this.rbstate,
					this.rbstate = rbstate);
		}
	}
}

Beim Versuch die Datenbindung in meinem gerade aktuell bearbeiteten Programm zu integrieren hatte ich zunächst kein Glück. Das Problem bestand in der nicht Bean – Konformen Form meiner Daten. In der Modellklasse hatte ich eine Variable vColor. Die Setter und Getter habe ich selbst manuell zugefügt: getVColor und setVColor. Damit konnte in der Datenbindung die Variable vColor nicht gefunden werden. Richtig wäre gewesen: getvColor und setvColor, also mit einem kleinen v, welches nicht in einen Großbuchstaben gewandelt wird, da der folgende Buchstabe bereits ein Großbuchstabe ist. Gefunden unter

Java Bean Getters/Setters

Dieser Fehler hat mich Stunden der Suche gekostet.