如何添加响应任何首选项更改的 IPreferenceChangeListener?
How can I add an IPreferenceChangeListener that responds to any preference change?
我想添加一个将在 任何 Eclipse 首选项更改时触发的侦听器。
我知道如何使用声明页面的 UI 插件的 Activator 为特定的首选项页面执行此操作。您可以使用从 Activator.start() 方法调用的以下 API:
getPreferenceStore().addPropertyChangeListener(IPropertyChangeListener listener)
但我希望在任何偏好更改时都能通知收听者。我尝试了以下方法,从我的 Activator.start() 方法调用:
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
public class Activator extends AbstractUIPlugin {
...
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
addMyPreferenceChangeListener();
}
private IPreferenceChangeListener fPreferenceChangeListener;
private void addMyPreferenceChangeListener() {
fPreferenceChangeListener = new IPreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent event) {
System.err.println("PreferenceChangeEvent");
}
};
IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode("/");
prefs.addPreferenceChangeListener(fPreferenceChangeListener);
}
}
我希望getNode的“/”可以指示偏好的根,但这似乎行不通;当我更改首选项时,println() 不会执行(例如:Window > Preferences > General > Always 运行 in background)。
没有办法让所有节点都收到通知的单个侦听器,您必须为您感兴趣的每个节点添加一个侦听器。
您可以使用 IPreferenceNodeVisitor
找到所有现有节点
IPreferencesService prefsService = Platform.getPreferencesService();
IEclipsePreferences root = prefsService.getRootNode();
root.accept(visitor);
您还必须使用 IEclipsePreferences.addNodeChangeListener
才能获知新节点。
另请注意,您的激活器的 start
方法不会 运行 直到您的插件中的某些其他代码被使用 - 它通常不会 运行 在 Eclipse 启动期间。
感谢 greg-449 的回答。这是我的最终代码供参考。
首选项侦听器是从 Activator 启动方法添加的。请注意,此插件在启动时使用 extension point="org.eclipse.ui.startup"
启动。
插件停止时会删除侦听器。
对首选项的任何更改都会导致打印 "PreferenceChangeEvent"。我抓住这一点来做我想做的实际工作;未显示。
如果创建了一个新的首选项节点(例如创建一个新的环境变量(Window > Preferences > C/C++ > Build > Environment)并按 Apply)然后打印 "PreferenceChangeEvent"。每当变量的值随后在首选项中更改时也会打印。
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IPreferenceNodeVisitor;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.service.prefs.BackingStoreException;
public class Activator extends AbstractUIPlugin {
...
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
addPreferenceChangeListeners();
}
public void stop(BundleContext context) throws Exception {
removePreferenceChangeListeners();
plugin = null;
super.stop(context);
}
private IPreferenceChangeListener fPreferenceChangeListener;
private void addPreferenceChangeListeners() {
/*
* Create a single preference change listener; the same listener is
* used for all the Preference Nodes.
*/
fPreferenceChangeListener = new IPreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent event) {
System.err.println("PreferenceChangeEvent");
}
};
IPreferencesService prefsService = Platform.getPreferencesService();
IEclipsePreferences root = prefsService.getRootNode();
/*
* Create a visitor for adding the pref change listener to each node.
*/
IPreferenceNodeVisitor addingVisitor = new IPreferenceNodeVisitor() {
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
if(null!=fPreferenceChangeListener) {
System.out.println("Adding pref change listener");
node.addPreferenceChangeListener(fPreferenceChangeListener);
/*
* Add a addNodeChangeListener so that if any new preference nodes
* are added they will also have our listener added too.
*/
node.addNodeChangeListener(new INodeChangeListener() {
@Override
public void removed(NodeChangeEvent event) {
System.out.println("removed: event=" + event.toString());
}
@Override
public void added(NodeChangeEvent event) {
System.out.println("added: event=" + event.toString());
IEclipsePreferences node = (IEclipsePreferences) event.getChild();
node.addPreferenceChangeListener(fPreferenceChangeListener);
}
});
}
return true;
}
};
/*
* Add the listener to the root and all its children
*/
try {
root.accept(addingVisitor);
} catch (BackingStoreException e) {
e.printStackTrace();
}
}
private class PreferenceChangeRemovingVisitor implements IPreferenceNodeVisitor {
@Override
public boolean visit(IEclipsePreferences node) {
if(null!=fPreferenceChangeListener) {
System.out.println("Removing pref change listener");
node.removePreferenceChangeListener(fPreferenceChangeListener);
}
return true;
}
}
private void removePreferenceChangeListeners() {
IPreferencesService prefsService = Platform.getPreferencesService();
IEclipsePreferences root = prefsService.getRootNode();
IPreferenceNodeVisitor removingVisitor = new PreferenceChangeRemovingVisitor();
try {
root.accept(removingVisitor);
} catch (BackingStoreException e) {
e.printStackTrace();
}
fPreferenceChangeListener = null;
}
}
我想添加一个将在 任何 Eclipse 首选项更改时触发的侦听器。
我知道如何使用声明页面的 UI 插件的 Activator 为特定的首选项页面执行此操作。您可以使用从 Activator.start() 方法调用的以下 API:
getPreferenceStore().addPropertyChangeListener(IPropertyChangeListener listener)
但我希望在任何偏好更改时都能通知收听者。我尝试了以下方法,从我的 Activator.start() 方法调用:
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
public class Activator extends AbstractUIPlugin {
...
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
addMyPreferenceChangeListener();
}
private IPreferenceChangeListener fPreferenceChangeListener;
private void addMyPreferenceChangeListener() {
fPreferenceChangeListener = new IPreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent event) {
System.err.println("PreferenceChangeEvent");
}
};
IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode("/");
prefs.addPreferenceChangeListener(fPreferenceChangeListener);
}
}
我希望getNode的“/”可以指示偏好的根,但这似乎行不通;当我更改首选项时,println() 不会执行(例如:Window > Preferences > General > Always 运行 in background)。
没有办法让所有节点都收到通知的单个侦听器,您必须为您感兴趣的每个节点添加一个侦听器。
您可以使用 IPreferenceNodeVisitor
IPreferencesService prefsService = Platform.getPreferencesService();
IEclipsePreferences root = prefsService.getRootNode();
root.accept(visitor);
您还必须使用 IEclipsePreferences.addNodeChangeListener
才能获知新节点。
另请注意,您的激活器的 start
方法不会 运行 直到您的插件中的某些其他代码被使用 - 它通常不会 运行 在 Eclipse 启动期间。
感谢 greg-449 的回答。这是我的最终代码供参考。
首选项侦听器是从 Activator 启动方法添加的。请注意,此插件在启动时使用 extension point="org.eclipse.ui.startup"
启动。
插件停止时会删除侦听器。
对首选项的任何更改都会导致打印 "PreferenceChangeEvent"。我抓住这一点来做我想做的实际工作;未显示。 如果创建了一个新的首选项节点(例如创建一个新的环境变量(Window > Preferences > C/C++ > Build > Environment)并按 Apply)然后打印 "PreferenceChangeEvent"。每当变量的值随后在首选项中更改时也会打印。
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IPreferenceNodeVisitor;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.service.prefs.BackingStoreException;
public class Activator extends AbstractUIPlugin {
...
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
addPreferenceChangeListeners();
}
public void stop(BundleContext context) throws Exception {
removePreferenceChangeListeners();
plugin = null;
super.stop(context);
}
private IPreferenceChangeListener fPreferenceChangeListener;
private void addPreferenceChangeListeners() {
/*
* Create a single preference change listener; the same listener is
* used for all the Preference Nodes.
*/
fPreferenceChangeListener = new IPreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent event) {
System.err.println("PreferenceChangeEvent");
}
};
IPreferencesService prefsService = Platform.getPreferencesService();
IEclipsePreferences root = prefsService.getRootNode();
/*
* Create a visitor for adding the pref change listener to each node.
*/
IPreferenceNodeVisitor addingVisitor = new IPreferenceNodeVisitor() {
public boolean visit(IEclipsePreferences node) throws BackingStoreException {
if(null!=fPreferenceChangeListener) {
System.out.println("Adding pref change listener");
node.addPreferenceChangeListener(fPreferenceChangeListener);
/*
* Add a addNodeChangeListener so that if any new preference nodes
* are added they will also have our listener added too.
*/
node.addNodeChangeListener(new INodeChangeListener() {
@Override
public void removed(NodeChangeEvent event) {
System.out.println("removed: event=" + event.toString());
}
@Override
public void added(NodeChangeEvent event) {
System.out.println("added: event=" + event.toString());
IEclipsePreferences node = (IEclipsePreferences) event.getChild();
node.addPreferenceChangeListener(fPreferenceChangeListener);
}
});
}
return true;
}
};
/*
* Add the listener to the root and all its children
*/
try {
root.accept(addingVisitor);
} catch (BackingStoreException e) {
e.printStackTrace();
}
}
private class PreferenceChangeRemovingVisitor implements IPreferenceNodeVisitor {
@Override
public boolean visit(IEclipsePreferences node) {
if(null!=fPreferenceChangeListener) {
System.out.println("Removing pref change listener");
node.removePreferenceChangeListener(fPreferenceChangeListener);
}
return true;
}
}
private void removePreferenceChangeListeners() {
IPreferencesService prefsService = Platform.getPreferencesService();
IEclipsePreferences root = prefsService.getRootNode();
IPreferenceNodeVisitor removingVisitor = new PreferenceChangeRemovingVisitor();
try {
root.accept(removingVisitor);
} catch (BackingStoreException e) {
e.printStackTrace();
}
fPreferenceChangeListener = null;
}
}