Правильный способ привязки группы переключателей с помощью привязки данных JFace

Мне было интересно, может ли кто-нибудь объяснить мне, как я могу правильно привязать группу переключателей к логической переменной в модели, используя привязку данных JFace.

Позвольте мне сначала объяснить ситуацию: я создал класс, который представляет группу кнопок SWT (со стилем, установленным на «SWT.RADIO»), который состоит из трех элементов: метки с вопросом и двух кнопок, одна для ответ «да» и один - «нет». Я хотел бы создать привязку к логической переменной в модели таким образом, чтобы, когда пользователь выбирает радиокнопку «да», логическое значение имеет значение true, а когда он / она выбирает кнопку «нет», логическое значение установлено значение false.

Вот код моего класса:

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


}

Теперь, как видите, я привязываю свою кнопку «да» к логическому значению. В частности, значение будет привязано к событию SWT.selection. Похоже, это единственное допустимое событие для привязки радиокнопки. Однако из-за этого после выбора кнопки «нет» значение логического значения остается неизменным (поскольку не было запущено событие SWT.selection для кнопки «да»).
Что я могу сделать, чтобы это сделать работать должным образом, т.е. иметь возможность изменять значение логического значения в модели в зависимости от того, какую из кнопок выбирает пользователь? Я упустил здесь что-то очевидное? Спасибо!


person Sandman    schedule 16.03.2009    source источник


Ответы (6)


Это похоже на привязку POJO к свойству.

Это означает, что у вас должен быть один объект с двумя вашими кнопками, реализующими IObservable, а затем привязать его к своему ресурсу.
Как вы упомянули в комментариях, вам следует расширить AbstractObservable.

У вас есть пример такого расширения здесь с этим классом Test о наблюдаемом списке (не обязательно то, что вам нужно, но это может дать вам представление об использовании Observable, когда дело доходит до обнаружения изменения при уведомлении)

person VonC    schedule 17.03.2009
comment
Хммм ... да, кажется, это самый элегантный способ решить эту проблему. Спасибо за ответ, приму, если никто не придумает ничего лучше. Кстати, мне кажется, что мне, вероятно, следует расширить AbstractObservable вместо того, чтобы напрямую реализовывать IObservable. - person Sandman; 18.03.2009
comment
Я думаю, что SeB.Fr предоставил еще более элегантное и простое решение с использованием SelectObservableValue. - person janhink; 05.02.2014

Думаю, я нашел для этого наиболее подходящую реализацию. Вам необходимо использовать org.eclipse.core.databinding.observable.value.SelectObservableValue. вот код

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

Это, конечно, работает для всех видов перечислений или других выбираемых значений. Вы, конечно, можете использовать String YES и NO, но я предпочитаю перечисления

person SeB.Fr    schedule 28.02.2013
comment
Думаю, это самое элегантное решение, спасибо! - person janhink; 05.02.2014

Если вы используете элемент управления Nebula RadioGroup, вы можете использовать RadioGroupViewer и привязать выбор средства просмотра, например любой другой зритель, например ComboViewer

person qualidafial    schedule 09.12.2010

Радиокнопки внутри одного и того же составного элемента будут действовать как группа, поэтому только одна кнопка будет иметь истинное значение, а все остальные должны иметь ложное значение. Наряду с этим фактом, что ObservationSelection для кнопки «Да» должно быть достаточно, чтобы отразить выбранное значение «да» или «нет» на стороне свойства модели.

Другими словами, модифицированный конструктор будет выглядеть так.

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

Я попробовал это и обнаружил, что работает хорошо. Просто проверьте.

person Community    schedule 29.07.2009

Это то, к чему я пришел при сопоставлении переключателей с перечислением (я продолжу и сделаю его многоразовым в нашем проекте) - использование ISWTObservableValue экономит усилия по добавлению слушателей:

    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);
person Eugene    schedule 17.09.2012

Это должно сработать практически без усилий, и все мы знаем, что это лучший ответ, верно?

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));
}
person Mostafa Zeinali    schedule 28.06.2015