博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jface databinding:输入无效数值时强制恢复初始值-updateModelToTarget
阅读量:2172 次
发布时间:2019-05-01

本文共 6008 字,大约阅读时间需要 20 分钟。

解决方案

Binding类中的updateModelToTarget方法,就是实现从数据对象到目标对象(比如Widget)的更新方法,只要调用这个方法就能强制让数据对象的内容同步到目标对象。如下是抽象方法updateModelToTarget的说明:

/**     * Updates the target's state from the model's state at the next reasonable     * opportunity. There is no guarantee that the state will have been updated     * by the time this call returns.     * 在合适的机会将model状态更新到target,因为是异步更新,所以不保证当方法返回时target更新完成。     */    public abstract void updateModelToTarget();

问题描述

如下代码显示一个简单的对话框,Text文本框中初始是个浮点数0.5,当修改文本框中的内容不符合float数值格式时,左上角会提示出错。点击下面的”恢复初始值”按钮,希望能恢复初始值0.5。

这里写图片描述

package testwb;import org.eclipse.jface.dialogs.Dialog;import org.eclipse.jface.dialogs.IDialogConstants;import org.eclipse.swt.graphics.Point;import org.eclipse.swt.widgets.Composite;import org.eclipse.swt.widgets.Control;import org.eclipse.swt.widgets.Shell;import org.eclipse.swt.SWT;import org.eclipse.swt.widgets.Text;import org.eclipse.core.databinding.Binding;import org.eclipse.core.databinding.DataBindingContext;import org.eclipse.core.databinding.observable.value.IObservableValue;import org.eclipse.core.databinding.observable.value.WritableValue;import org.eclipse.jface.databinding.swt.WidgetProperties;import org.eclipse.swt.widgets.Display;import org.eclipse.core.databinding.observable.Realm;import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport;import org.eclipse.jface.databinding.swt.DisplayRealm;import org.eclipse.swt.widgets.Button;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;public class TestPojoBinding5 extends Dialog {
private DataBindingContext m_bindingContext; // floatValue 初始值0.5f private final WritableValue
floatValue = new WritableValue
(Float.valueOf(0.5f), Float.class); // Text文本框对象 private Text floatValueText; private Binding bindValue; /** * Create the dialog. * @param parentShell */ public TestPojoBinding5(Shell parentShell) { super(parentShell); } /** * Create contents of the dialog. * @param parent */ @Override protected Control createDialogArea(Composite parent) { Composite container = (Composite) super.createDialogArea(parent); container.setLayout(null); Button btnNewButton = new Button(container, SWT.NONE); // 点击“恢复初始值”按钮时,将floatValue重新设置为初始值 btnNewButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { floatValue.setValue(Float.valueOf(0.5f)); } }); btnNewButton.setBounds(38, 154, 80, 27); btnNewButton.setText("恢复初始值"); floatValueText = new Text(container, SWT.BORDER); floatValueText.setBounds(38, 27, 80, 23); return container; } /** * Create contents of the button bar. * @param parent */ @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); m_bindingContext = initDataBindings(); } /** * Return the initial size of the dialog. */ @Override protected Point getInitialSize() { return new Point(362, 298); } public static void main(String[] args) { Display display = Display.getDefault(); Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() { public void run() { try { TestPojoBinding5 setting = new TestPojoBinding5(null); setting.open(); } catch (Exception e) { e.printStackTrace(); } } }); } protected DataBindingContext initDataBindings() { DataBindingContext bindingContext = new DataBindingContext(); // IObservableValue observeTextFloatValueTextObserveWidget = WidgetProperties.text(SWT.Modify).observe(floatValueText); // 将floatValueText和floatValue进行数据绑定 bindValue=bindingContext.bindValue(observeTextFloatValueTextObserveWidget, floatValue, null, null); // 创建验证错误提示组件(就是Text文本框左上角的红X号,数据验证出错时显示), ControlDecorationSupport.create(bindValue, SWT.TOP | SWT.LEFT); return bindingContext; }}

实际的结果是:

当修改Text文本框内容为一个合法的浮点数时,点击”恢复初始值”按钮Text显示内容的确可以恢复到初始值0.5,
但是当输入的内容无效,不是一个数字时,点击”恢复初始值”按钮也恢复不到初始值?
这是为什么呢?难道jface有bug?

问题溯源

通过跟踪代码搞清楚了原因:

假设当前Text的内容是初始值0.5,然后修改Text的内容,
不论Text文本框的内容是否为有效数字,点击”恢复初始值”按钮时,floatValue.setValue(Float.valueOf(0.5f));确实被执行了,
但区别是当输入Text文本框的内容为无效数字时,floatValue的内容并不会被修改,也就是还保持之前的值(0.5),此时再点击”恢复初始值”按钮时,设置的值还是0.5,floatValue并没有改变,所以没有触发Text的更新。
再做一个试验来验证上面的逻辑:
如果先将Text的内容从0.5改为另一个有效数字(比如0.9)—(此时floatValue被更新为0.9),然后再改为一个无效数字hello,然后点击”恢复初始值”按钮,则Text的内容正常恢复。
由此找出了问题的原因:当数据对象更新的值与原值相等时,setValue不能触发Widget组件的更新。
怎么解决呢?仔细研究了,org.eclipse.core.databinding.ValueBinding代码中的数据更新的方法doUpdate,及其调用层次结构,由此就找到了本文开始的答案。
这里写图片描述
ValueBinding继承于抽象类Binding,Binding类中的updateModelToTarget方法,就是实现从数据对象到目标对象(比如Widget)的更新方法,只要调用这个方法就能强制让数据对象的内容同步到目标对象。

修改代码

所以解决这个问题的办法很简单,如下增加一行代码即可:

// 点击“恢复初始值”按钮时,将floatValue重新设置为初始值        btnNewButton.addSelectionListener(new SelectionAdapter() {            @Override            public void widgetSelected(SelectionEvent e) {                floatValue.setValue(Float.valueOf(0.5f));                // 强制更新Text组件内容                bindValue.updateModelToTarget();            }        });

当然仔细想想上面这样修改的确是简单,但在Text已经被更新的情况下,会多一次强制更新的动作,所以如果代码写得更仔细点,应该是这样:

// 点击“恢复初始值”按钮时,将floatValue重新设置为初始值        btnNewButton.addSelectionListener(new SelectionAdapter() {            @Override            public void widgetSelected(SelectionEvent e) {                // 判断floatValue是否等于初始值(0.5f),如果是的话,只做强制更新                if(floatValue.getValue()==0.5f)                    bindValue.updateModelToTarget();                else// 否则就更新floatValue,Text会自动更新。                    floatValue.setValue(Float.valueOf(0.5f));                           }        });
你可能感兴趣的文章
TensorFlow-11-策略网络
查看>>
浅谈 GBDT
查看>>
如何选择优化器 optimizer
查看>>
一文了解强化学习
查看>>
CART 分类与回归树
查看>>
seq2seq 的 keras 实现
查看>>
seq2seq 入门
查看>>
什么是 Dropout
查看>>
用 LSTM 做时间序列预测的一个小例子
查看>>
用 LSTM 来做一个分类小问题
查看>>
详解 LSTM
查看>>
按时间轴简述九大卷积神经网络
查看>>
详解循环神经网络(Recurrent Neural Network)
查看>>
为什么要用交叉验证
查看>>
用学习曲线 learning curve 来判别过拟合问题
查看>>
用验证曲线 validation curve 选择超参数
查看>>
用 Grid Search 对 SVM 进行调参
查看>>
用 Pipeline 将训练集参数重复应用到测试集
查看>>
PCA 的数学原理和可视化效果
查看>>
机器学习中常用评估指标汇总
查看>>