Modo corretto di associare un gruppo di pulsanti di opzione utilizzando l'associazione dati JFace

StackOverflow https://stackoverflow.com/questions/650959

Domanda

Mi chiedevo se qualcuno potesse spiegarmi come avrei potuto legare correttamente un gruppo di pulsanti di opzione a una variabile booleana nel modello usando l'associazione dati JFace.

Vorrei prima spiegare la situazione: ho creato una classe che rappresenta un gruppo di pulsanti SWT (con lo stile impostato su "SWT.RADIO") che consiste di tre elementi: un'etichetta con la domanda e due pulsanti, uno per il "sì" risposta e una per un "no". Vorrei creare un'associazione a una variabile booleana nel modello in modo tale che quando un utente seleziona il "sì" pulsante di opzione il valore booleano è impostato su true e quando seleziona il "no" il pulsante booleano è impostato su false.

Ecco il codice della mia classe:

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


}

Ora, come puoi vedere, sto vincolando il mio "sì" pulsante per il booleano. In particolare, il valore verrà associato all'evento SWT.selection. Questo è, a quanto pare, l'unico evento valido per l'associazione di un pulsante di opzione. Tuttavia, per questo motivo, una volta che il " no " pulsante è selezionato, il valore del valore booleano rimane invariato (poiché non è stato attivato alcun evento di selezione SWT sul pulsante "Sì").
Cosa posso fare per fare in modo che funzioni come dovrebbe, ovvero per poter cambiare il valore del valore booleano nel modello in base a quale dei pulsanti l'utente seleziona? Mi sto perdendo qualcosa di ovvio qui? Grazie!

È stato utile?

Soluzione

Sembra simile a che lega un POJO a una proprietà .

Ciò significa che dovresti avere un oggetto con i tuoi due pulsanti che implementano un IObservable , quindi associarlo alla tua proprietà.
Come menzionato nei commenti, è necessario estendere AbstractObservable .

Hai un esempio di tale estensione qui con questo test di classe su un elenco osservabile (non è necessario ciò di cui hai bisogno ma può darti idee sull'uso di Observable quando si tratta di rilevare la modifica dopo la notifica)

Altri suggerimenti

Penso di aver trovato l'implementazione più appropriata per questo. Devi utilizzare org.eclipse.core.databinding.observable.value.SelectObservableValue . ecco il codice

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

Funziona ovviamente per tutti i tipi di enumerazioni o altri tipi di valori selezionabili. Ovviamente potresti usare la tua stringa YES e NO, ma preferisco gli enum

Se utilizzi il Nebula RadioGroup puoi utilizzare RadioGroupViewer e associare il selezione del visualizzatore come qualsiasi altro visualizzatore, ad es ComboViewer

I pulsanti di opzione all'interno dello stesso composito fungerebbero da gruppo, quindi solo un pulsante avrà un valore vero e tutti gli altri dovrebbero avere un valore falso. Insieme a questo fatto, il pulsante observSelection su Sì dovrebbe essere sufficiente per riflettere il valore selezionato di sì o no, sul lato delle proprietà del modello.

O in altre parole, il costruttore modificato sarebbe simile a questo.

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

Ho provato questo e ho trovato che funziona bene. Dai un'occhiata.

Questo è quello che ho scoperto quando ho mappato i pulsanti di opzione su enum (procederò e lo renderò riutilizzabile nel nostro progetto) - l'uso di ISWTObservableValue risparmia lo sforzo di aggiungere gli ascoltatori:

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

Questo dovrebbe funzionare con poco o nessun sforzo, e sappiamo tutti che è il miglior tipo di risposta, giusto?

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));
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top