You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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();
}

问题原因

  1. 未将PathEditor注册到页面:原代码中创建PathEditor后未调用addField(pathEditor),导致页面未为其绑定PropertyChangeListener,监听器根本无法接收事件。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:17:39