Pronux Wiki
Menu

UnterstützungVonFormularen

Formulare (Forms) werden genutzt, um Eingaben vom Nutzer entgegen zu nehmen.

Ein Formular erzeugen

Subklasse AbstractForm.

public class CustomerForm extends AbstractForm 
{

 public CustomerForm(FormModel formModel) 
  {
   super(formModel, "customerForm");
  }

 protected JComponent createFormControl() 
  {
   FormLayout layout = new FormLayout("left:pref, 5dlu, pref:grow");
   BeanFormBuilder formBuilder = new JGoodiesBeanFormBuilder(getFormModel(), layout);
   formBuilder.add("number");
   formBuilder.add("name");
   return formBuilder.getForm();
  }
}

Zusammengesetzte Formulare

Die CompoundForm Klasse wird genutzt um verschiedene "formpages" in einem logischen Formular zu kombinieren. Wenn man z.B. einen Wizard mit mehreren Seiten erzeugen will, wobei jede Seite ein formular enthält, so kann man diese zusammenfassen, in dem man die CompoundForm Klasse nutzt.

Formular Erzeuger

Engl: FormBuilders Um ein erweitertes Layout zu erstellen, kann einen FormBuilder nutzen. Diesen gibt es in mehreren Ausführungen.

TableFormBuilder

Beispiel:


TableFormBuilder formBuilder = new TableFormBuilder(formModel);

formBuilder.addSeparator("Name");
formBuilder.row();
formBuilder.add("title");
formBuilder.add("firstName");
formBuilder.add("lastName");
formBuilder.row();
formBuilder.addSeparator("Address");
formBuilder.row();
formBuilder.add("address1");
formBuilder.row();
formBuilder.add("address2");
formBuilder.row();
formBuilder.add("city");
formBuilder.add("postcode", "colSpec=2cm");
formBuilder.row();
formBuilder.add("state");
formBuilder.row();
formBuilder.add("country");

return formBuilder.getForm();

GridBagLayoutFormBuilder

Nutzt das GridBagLayout.

Nutzung des Formulars

In einem Wizard

Dazu erezugt man eine FormBackedWizardPage und fügt sie dem Wizard hinzu.

In einem Dialog

Customer customer = ...;
FormModel formModel = SwingFormModel.createFormModel(customer);
CustomerForm form = new CustomerForm(formModel);
FormBackedDialogPage page = new FormBackedDialogPage(form);

TitledPageApplicationDialog dialog = new TitledPageApplicationDialog(page, getParentWindowControl()) 
 {
   protected void onAboutToShow() 
     {
       setEnabled(compositePage.isPageComplete());
     }

    protected boolean onFinish() {
    ownerFormModel.commit();
    clinic.storeOwner(owner);
    ownersTreeModel.nodeChanged(getSelectedOwnerNode());
    return true;
 }
};

dialog.showDialog();

Validierung

Zur Zeit gibt es 2 Möglichkeiten: Man kann Validierungsregeln registrieren indem man eine RuleSource Instanz konfiguriert, wie es zum Beispiel die "ValidationRulesSource" Klasse im Petclinic example macht, oder das FormObject implementiert das Interface RulesProvider, wie es z.B. die Klasse LoginSessionDetails macht.

RuleSource Ansatz

Man benötigt eine RuleSource Implementierung (Als Beispiel dazu siehe die Klasse PetClinicValidationRulesSource).

Hier sind die Regeln definiert für eine Owner Klasse (firstName und lastName Attribute sind verpflichtend, maximal 25 Zeichen lang und müssen alphabetic sein. Das address Attribute ist verpflichtend)

public class PetClinicValidationRulesSource extends DefaultRulesSource 
 {
   public PetClinicValidationRulesSource() 
     {
      addRules(createOwnerRules());
     }

   private Rules createOwnerRules() 
    {
     Rules rules = Rules.createRules(Owner.class);
     rules.add("firstName", getNamePropertyConstraint());
     rules.add("lastName", getNamePropertyConstraint());
     rules.add("address", required());
     return rules;
    }

  private Constraint getNamePropertyConstraint() 
   {
    return all(new Constraint[] { required(), maxLength(25), regexp("[a-zA-Z]*", "alphabetic") });
   }
 }

Die RulesSource ist in der Datei rich-clientappication-context.xmlregistriert:

<bean id="rulesSource" class="org.springframework.richclient.samples.petclinic.domain.PetClinicValidationRulesSource"/>

Dies führt dazu, dass alle Formulare, die die Klasse Owner verwenden, diese Regeln nutzen.

RulesProvider Ansatz

Das Formular muss das Interface RulesProvider implementieren. Dieses Interface definiert eine Methode: public PropertyConstraint getRules(String property). Das folgende Beispiel nutzt die DefaultRulesSource, um diese Methode zu implementieren.

Formular Object:

public class TestFormBean implements RulesProvider 
 {

  RulesSource rulesSource = new DefaultRulesSource();
  private String inputString;

  public TestFormBean() 
  {
   rulesSource.addRules(getRules());
  }

  private Rules getRules() 
  {
   Rules rules = Rules.createRules(getClass());
   Constraints c = Constraints.instance();
   rules.add("inputString", c.required());

   return rules;
  }

 // implementation of RulesProvider interface
 public PropertyConstraint getRules(String property) 
  {
   return rulesSource.getRules(getClass(), property);
  }
}

Formular Instanz

public class TestForm extends AbstractForm 
 {

  private TestFormBean testFormBean = new TestFormBean();

  public LoginForm() 
   {
    super("general");
    setFormModel(SwingFormModel.createFormModel(this.testFormBean));
   }

   protected JComponent createFormControl() 
   {
    FormLayout layout = new FormLayout("left:pref, 5dlu, pref:grow");
    BeanFormBuilder formBuilder = new JGoodiesBeanFormBuilder(
    getFormModel(), layout);
    formBuilder.add("inputString");

    return formBuilder.getForm();
   }

  public void commit() throws AuthenticationException 
  {
    // do your stuff here
  }
}

Bedingungen

Engl: Constraints

Wie man eine eigene Bedingung implementiert.

Die Fehlermeldung internationalisieren

Die eigene Bedingung muss das Interface TypeResolvable implementieren. Es gibt eine TypeResolvableConstraint Hilfsklasse, von welcher man seine Klasse ableiten kann. TypeResolvables wird automatisch durch die Spring message sources aufgelöst.

public class MyCustomConstraint extends TypeResolvableConstraint 
{
  public MyCustomConstraint() 
   {
    super("customConstraint");
   }

  public boolean test(Object argument) 
  {
   // implementation of constraint
  }
}

Binden

Engl: Binding

Die Bindung eines Wertes im Control mit dem dahinterliegenden Domain Objekts geschieht mit einem Bindin Objekt, welches normalerweise von einem Binder erzeugt wird. Wenn man z.B. das Framework beauftragt, ein Control für die bar Eigenschaft des Foo Objekts zu erzeugen, wobei bar ein String ist, gibt ein TextComponentBinder ein TextComponentBinding Objekt zurück, welches sich darum kümmert, das das Domain Objekt mit dem Formular synchron bleibt.

Falls man dies alles direct machen wollte, würde es so aussehen:

BindingFactory bindingFactory = new SwingBindingFactory(formModel);
Binding fooBinding = bindingFactory.createBoundTextField("bar");
JComponent fooControl = fooBinding.getControl();

Dies mag nach einer Menge Arbeit aussehen, nur um ein Textfeld zu erzeugen, aber dabei geschieht eine Menge Arbeit automatisch, z.B. die Registrierung sowohl der Eigenschaft des Objekts und des Controls für die Validierungsunterstützung, die automatische Synchronisierung und noch jede Menge mehr. Es bedeutet ausserdem, dass die Art des zu verwendenden Controls automatisch erfasst wird und der Control erzeugt wird. Damit kann man Änderungen an der Applikation an einem Ort vornehmen (z.B. die Standard JTextArea zu einer Komponente ändern, die volle TextEditor Eigenschaften besitzt). Welches Binder für eine Eigenschaft ausgewählt wird, kann bestimmt werden durch den Typ der Eigenschaft, durch die Property einer Klasse selbst und noch durch viele andere Eigenschaften.

Binder

Ein Beispiel eines Binder:

/**
* This provides a {@link Binder} for {@link Long} that only allows
* valid "Long" values to be entered into the control.
*/
public class LongBinder extends AbstractBinder 
{
  public LongBinder() 
   {
     super(Long.class);
   }

  protected JComponent createControl(Map context) 
   {
    return new LongTextField();
   }

  protected Binding doBind(JComponent control, FormModel formModel, String formPropertyPath, Map context) 
  {
    return new TextComponentBinding((JTextComponent)control, formModel, formPropertyPath);
  }

  private static class LongTextField extends JFormattedTextField 
   {
    public boolean isEditValid() 
     {
     final String text = getText();
     if (text == null) return true;
     try 
      {
       Long.parseLong(text);
       return true;
      }
     catch (NumberFormatException e) 
      {
       return false;
      }
    }
  }
}

BinderSelectionStrategy

Wenn man die Menge der automatischen Bindings ändern will, oder ein neues Binding hinzufügen will, muss man einfach das Interface BinderSelectionStrategy implementieren. Ein Beispiel für eine eigene BinderSelectionStrategy könnte folgender Code sein:

public class MyBinderSelectionStrategy extends SwingBinderSelectionStrategy 
{
  protected void registerDefaultBinders() 
   {
    super.registerDefaultBinders();
    registerBinderForPropertyType(Long.class, new LongBinder());
    registerBinderForPropertyType(Date.class, new DateBinder());
    registerBinderForPropertyType(Foo[].class, new FooArrayBinder());
   }
}

Damit die Applikation die eigene BinderSelectionStrategy verwendet, muss abschliessend noch folgende Zeile zur Datei application-context.xml hinzugefügt werden:

<bean id="binderSelectionStrategy" class="bar.foo.MyBinderSelectionStrategy"/>

Diese Bean muss nun noch den ApplicationServices als neue Binder Selection Strategy bekannt gegeben werden:

<bean id="applicationServices"
class="org.springframework.richclient.application.support.DefaultApplicationServices">
...
  <property name="binderSelectionStrategyId">
    <idref bean="binderSelectionStrategy"/>
  </property>
</bean>

Go to top   Edit this page.   More info...   Attach file...

This page last changed on 10-Nov-2006 13:30:12 CET by PeterSchneider-Manzell.