为何PathEditor的PropertyChangeListener无响应?
问题:PathEditor不触发PropertyChangeEvent,无任何响应
在基于FieldEditorPreferencePage的开发中,PathEditor是唯一不响应PropertyChangeEvent的字段编辑器。无论添加或删除路径,均无任何反馈,org.eclipse.jface.preference.FieldEditor.fireValueChanged方法未被触发。
已确认:
- 页面内其他继承自
StringFieldEditor的编辑器(如FileEditor、DirectoryEditor)均正常触发事件 - 所有编辑器已通过
setPropertyChangeListener正确设置监听
相关代码
PreferencePage类
public class PreferencePage extends ValidatingPreferencePage implements IWorkbenchPreferencePage { private String[] styleSheetTypesAllowed = {"xslt","xsl"}; private String[] configTypesAllowed = {"lcc","qml"}; private CustomFileFieldEditor styleSheet; public PreferencePage() { super(GRID); setPreferenceStore(Activator.getDefault().getPreferenceStore()); } @Override public void createFieldEditors() { Composite parent = getFieldEditorParent(); // some other fields added PathEditor pathEditor = new PathEditor( PreferenceConstants.P_CONFIGPATH, "Configuration paths", "Add directory", parent); } @Override protected void initialize() { super.initialize(); isLicense(); } @Override protected void performDefaults() { // license might be enabled from ini file. If so, keep fields enabled: enableFieldEditors(isLicense()); super.performDefaults(); } }
ValidatingPreferencePage类
public class ValidatingPreferencePage extends FieldEditorPreferencePage implements FieldEditors { // fields, constructors // super.fields is private - create own list @Override protected void addField(FieldEditor editor) { if (fields == null) fields = new ArrayList<>(); fields.add(editor); super.addField(editor); } @Override public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(FieldEditor.IS_VALID)) { boolean newValue = ((Boolean) event.getNewValue()).booleanValue(); // If the new value is true then we must check all field editors. // If it is false, then the page is invalid in any case. if (newValue) { checkState(); } else { validFileType = true; invalidFieldEditor = (FieldEditor) event.getSource(); setValid(newValue); } } // handle CTRL+V & delete whole string & focus lost if (event.getProperty().equals(FieldEditor.VALUE)) { validFileType = true; checkState(); } } private void setErrorMessagePP() { // set error messages } @Override protected void checkState() { //super.checkState(); // other code } public List<FieldEditor> getFieldEditorList() { return fields; } }
PreferencesValidation接口
public interface PreferencesValidation { public void enableValidation(boolean enableVal); public void setEmptyStringAllowed(boolean emptyStringAllowed); public void setEnabled(boolean newValue, Composite parent); public void refreshValidState(); public boolean checkState(); public boolean handlesLicense(); public String getDependsOn(); }
问题原因
- 未将PathEditor注册到页面:原代码中创建
PathEditor后未调用addField(pathEditor),导致页面未为其绑定PropertyChangeListener,监听器根本无法接收事件。 - PathEditor本身的事件触发逻辑缺失:
PathEditor继承自ListEditor,而ListEditor在添加/删除路径项时,默认不会主动触发VALUE类型的PropertyChangeEvent,也不会调用fireValueChanged方法。
解决方案
步骤1:注册PathEditor到页面
在创建PathEditor后,必须调用addField方法将其注册到偏好页,这样页面才会为它设置监听器:
@Override public void createFieldEditors() { Composite parent = getFieldEditorParent(); // some other fields added PathEditor pathEditor = new PathEditor( PreferenceConstants.P_CONFIGPATH, "Configuration paths", "Add directory", parent); addField(pathEditor); // 关键:注册编辑器到页面 }
步骤2:自定义PathEditor触发事件
由于原生PathEditor不会在内容变更时触发事件,需要自定义子类,重写操作方法并主动触发VALUE变更事件:
public class NotifyPathEditor extends PathEditor { public NotifyPathEditor(String name, String labelText, String browseButtonText, Composite parent) { super(name, labelText, browseButtonText, parent); } @Override protected void addPressed() { super.addPressed(); // 路径添加后触发VALUE变更事件 fireValueChanged(FieldEditor.VALUE, null, getPreferenceStore().getString(getPreferenceName())); } @Override protected void removePressed() { super.removePressed(); // 路径删除后触发VALUE变更事件 fireValueChanged(FieldEditor.VALUE, null, getPreferenceStore().getString(getPreferenceName())); } @Override protected void doubleClicked() { super.doubleClicked(); // 路径编辑后触发VALUE变更事件 fireValueChanged(FieldEditor.VALUE, null, getPreferenceStore().getString(getPreferenceName())); } }
步骤3:使用自定义的NotifyPathEditor
将原代码中的PathEditor替换为自定义的NotifyPathEditor:
@Override public void createFieldEditors() { Composite parent = getFieldEditorParent(); // some other fields added NotifyPathEditor pathEditor = new NotifyPathEditor( PreferenceConstants.P_CONFIGPATH, "Configuration paths", "Add directory", parent); addField(pathEditor); }
这样修改后,PathEditor在添加、删除、编辑路径时都会触发PropertyChangeEvent,页面的propertyChange方法就能接收到VALUE类型的事件,进而执行checkState等逻辑。
内容的提问来源于stack exchange,提问作者know
相关产品推荐
相关产品推荐

