2009-03-16 19 views
11

Me preguntaba si alguien podría explicarme cómo podría vincular correctamente un grupo de botones de opción a una variable booleana en el modelo utilizando el enlace de datos JFace.Forma correcta de vincular un grupo de botones de radio utilizando el enlace de datos JFace

Déjenme explicar la situación primero: he creado una clase que representa un grupo de botones SWT (con el estilo establecido en 'SWT.RADIO') que consta de tres elementos: una etiqueta con la pregunta y dos botones , uno para la respuesta "sí" y otro para un "no". Me gustaría crear un enlace a una variable booleana en el modelo de tal manera que cuando un usuario seleccione el botón de opción "sí", el booleano se establezca en verdadero, y cuando seleccione el botón "no", el booleano sea establecer en falso

Aquí está el código de mi clase:

private class YesOrNoRadioButtonGroup { 

private static final String YES = "yes"; 
private static final String NO = "no"; 
private Button m_yesButton; 
private Button m_noButton; 

public YesOrNoRadioButtonGroup(final Composite p_parent, 
           final String p_questionText, 
           final IObservableValue p_modelProperty 
           final DataBindingContext p_dbContext) 
{ 

    Composite radioButtonGroupContainer = new Composite(p_parent, SWT.NONE); 
    radioButtonGroupContainer.setLayout(new GridLayout()); 
    Label question = new Label(radioButtonGroupContainer, SWT.NONE); 
    question.setText(p_questionText); 


    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); 

    Listener yesOrNoRadioGroupListener = new Listener() { 

    public void handleEvent(Event p_event) { 

     Button button = (Button) p_event.widget; 

     if (m_yesButton.equals(button)) { 
     m_yesButton.setSelection(true); 
     m_noButton.setSelection(false); 
     } 
     else { 
     m_yesButton.setSelection(false); 
     m_noButton.setSelection(true); 
     } 
    } 
    }; 

    m_yesButton.addListener(SWT.Selection, yesOrNoRadioGroupListener); 
    m_noButton.addListener(SWT.Selection, yesOrNoRadioGroupListener); 

    p_dbContext.bindValue(SWTObservables.observeSelection(this.getYesButton()), 
     p_modelProperty, null, null);  
} 

public Button getYesButton() { 
    return m_yesButton; 
} 

public Button getNoButton() { 
    return m_noButton; 
}  


} 

Ahora, como se puede ver, estoy mi botón "sí" a la unión booleana. Específicamente, el valor se vinculará en el evento SWT.selection. Este es, al parecer, el único evento válido para el enlace de un botón de opción. Sin embargo, debido a esto, una vez que se selecciona el botón "no", el valor de boolean permanece sin cambios (ya que no se activó ningún evento SWT.selection en el botón "sí").
¿Qué puedo hacer para que esto funcione como se supone que debe, es decir, para poder cambiar el valor del booleano en el modelo en función de cuál de los botones selecciona el usuario? ¿Me estoy perdiendo algo obvio aquí? Gracias!

Respuesta

7

Parece similar a binding a POJO to a property.

Eso significa que debe tener un objeto con sus dos botones implementando un IObservable, y luego vincularlo a su propiedad.
Como mencionas en los comentarios, debes ampliar AbstractObservable.

Tienes un ejemplo de una extensión tal here with this class Test aproximadamente una lista observables (no es necesario lo que necesita, pero se le puede dar ideas sobre el uso de observables cuando se trata de detectar el cambio después de la notificación)

+0

Hmmm ... sí, esta parece ser la forma más elegante de resolver este problema. Tnx por la respuesta, la aceptaré si a nadie se le ocurre algo mejor. Por cierto, parece que probablemente debería extender AbstractObservable en lugar de implementar IObservable directamente. – Sandman

+0

Creo que SeB.Fr proporcionó una solución aún más elegante y simple usando SelectObservableValue. – janhink

+1

@eQui Estoy de acuerdo, y he votado a favor esa publicación. – VonC

2

La radio los botones dentro del mismo compuesto actuarían como un grupo, por lo tanto, solo un botón tendrá un valor verdadero y todos los demás deberían tener un valor falso. Junto con este hecho, el botón observeSelection on Yes debería ser suficiente para reflejar el valor seleccionado de yes o no, en el lado de la propiedad del modelo.

O en otras palabras, el constructor modificado se vería así.

public YesOrNoRadioButtonGroup(final Composite p_parent, 
      final String p_questionText, 
      final IObservableValue p_modelProperty, 
      final DataBindingContext p_dbContext) 
{ 
    Composite radioButtonGroupContainer = new Composite(p_parent, SWT.NONE); 
    radioButtonGroupContainer.setLayout(new GridLayout()); 
    Label question = new Label(radioButtonGroupContainer, SWT.NONE); 
    question.setText(p_questionText); 

    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); 
    p_dbContext.bindValue(SWTObservables.observeSelection(this.getYesButton()), 
       p_modelProperty, null, null); 
} 

Intenté esto y encontré que funcionaba bien. Solo echa un vistazo.

2

Si usa el control Nebula RadioGroup, puede usar RadioGroupViewer y vincular la selección del visor como cualquier otro visor, p. ComboViewer

0

Esto es lo que terminó con hacer el mapa de botones de radio para Enum (voy a proceder y que sea reutilizable en nuestro proyecto) - usando ISWTObservableValue ahorra el esfuerzo de añadir los oyentes:

final ISWTObservableValue upload = SWTObservables.observeSelection(btnUpload); 
    final ISWTObservableValue download = SWTObservables.observeSelection(btnDownload); 
    final ISWTObservableValue noTransfer = SWTObservables.observeSelection(btnNoTransfer); 
    final IObservableValue btns = new ComputedValue(ExecutableTransferModes.class) { 

     @Override 
     protected void doSetValue(final Object value) { 
      boolean u = false, d = false, n = false; 
      switch ((ExecutableTransferModes) value) { 
      case Upload: 
       u = true; 
       break; 
      case Download: 
       d = true; 
       break; 
      case Notransfer: 
       n = true; 
       break; 
      } 
      upload.setValue(u); 
      download.setValue(d); 
      noTransfer.setValue(n); 
     } 

     @Override 
     protected Object calculate() { 
      if (Boolean.TRUE.equals(upload.getValue())) { 
       return ExecutableTransferModes.Upload; 
      } else if (Boolean.TRUE.equals(download.getValue())) { 
       return ExecutableTransferModes.Download; 
      } else if (Boolean.TRUE.equals(noTransfer.getValue())) { 
       return ExecutableTransferModes.Notransfer; 
      } else { 
       return null; 
      } 
     } 
    }; 
    bindingContext.bindValue(btns, uploadProperty); 
6

pienso Encontré la implementación más adecuada para esto. Debe usar org.eclipse.core.databinding.observable.value.SelectObservableValue. Este es el código

class YesNoModel{ 
    public static enum RESPONSE {YES,NO}; 
    private RESPONSE value; 
    public RESPONSE getValue(){return value;} 
    public void setValue(RESPONSE value){this.value = value;} 
} 
class YouGraphicalClass { 
    YesNoModel yesNomodel = new YesNoModel(); 
    void iniDataBinding(){ 
     IObservableValue yesBtnSelection = SWTObservables.observeSelection(this.getYesButton()); 
     IObservableValue noBtnSelection = SWTObservables.observeSelection(this.getNoButton()); 
     SelectObservableValue featureRepoPolicyObservable = new SelectObservableValue(YesNoModel.RESPONSE.class); 
     featureRepoPolicyObservable.addOption(RESPONSE.YES, yesBtnSelection); 
     featureRepoPolicyObservable.addOption(RESPONSE.NO, noBtnSelection); 
     p_dbContext.bindValue(featureRepoPolicyObservable, 
       PojoObservables.observeValue(yesNomodel, "value")); 
    } 

Esto funciona, por supuesto, para al tipo de enumeraciones u otro tipo de valores seleccionables. Por supuesto, podría usar su cadena SÍ y NO, pero prefiero enumeraciones

+0

Creo que esta es la solución más elegante, ¡gracias! – janhink

0

Esto debería funcionar con poco o ningún esfuerzo, y todos sabemos que es el mejor tipo de respuesta, ¿verdad?

public static final void createAndBind(
    final DataBindingContext dbc, 
    final Composite parent, 
    final Object bean, 
    final List<Object> options, 
    final String fieldName, 
    final Class<?> fieldType) { 
    // 
    List<Button> radios = new ArrayList<>(); 
    Button b; 
    for (Object option : options) { 
     b = new Button(parent, SWT.RADIO); 
     b.setText(option.toString()); 
     b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 
     radios.add(b); 
    } 
    // 
    List<IObservableValue> iovs = new ArrayList<>(); 
    IObservableValue iov; 
    for (Button radio : radios) { 
     iov = SWTObservables.observeSelection(radio); 
     iovs.add(iov); 
    } 
    SelectObservableValue observable = new SelectObservableValue(fieldType); 
    // 
    for (int i = 0; i < options.size(); i++) { 
     observable.addOption(options.get(i), iovs.get(i)); 
    } 
    // 
    dbc.bindValue(observable, PojoObservables.observeValue(bean, fieldName)); 
} 
Cuestiones relacionadas