切换标签打开带图片Tooltip遇ImageRegistry键占用错误,如何正确配置?
解决SWT ImageRegistry键重复使用的问题
问题根源
你遇到的IllegalArgumentException: ImageRegistry key already in use是因为JFaceResources.getImageRegistry()返回的是全局单例注册表,而你的代码在切换标签页时会重复执行put操作——第一次注册键成功,后续再用同一个键添加就会触发冲突。
三种可行解决方案
1. 注册前先检查键是否存在
每次执行注册逻辑前,先判断目标键是否已在注册表中存在,仅当不存在时才执行put:
ImageRegistry registry = JFaceResources.getImageRegistry(); String closeIconKey = ControlVerifierToolTip.HEADER_CLOSE_ICON; if (!registry.containsKey(closeIconKey)) { registry.put(closeIconKey, ImageDescriptor.createFromFile(ControlsVerifierView.class, CLOSE_PNG)); }
这种方式简单直接,适合无法统一全局初始化的场景。
2. 移到全局初始化位置执行一次
如果这个图标是整个应用/插件共用的,把注册逻辑放到插件启动时执行(比如Activator的start方法),确保只注册一次:
@Override public void start(BundleContext context) throws Exception { super.start(context); ImageRegistry globalRegistry = JFaceResources.getImageRegistry(); globalRegistry.put(ControlVerifierToolTip.HEADER_CLOSE_ICON, ImageDescriptor.createFromFile(ControlsVerifierView.class, CLOSE_PNG)); }
之后在标签页代码里直接通过JFaceResources.getImageRegistry().get(...)获取图标即可,无需再执行注册。
3. 使用自定义ImageRegistry独立管理
如果不想依赖全局注册表,可以为标签页创建独立的ImageRegistry,和标签页生命周期绑定:
private ImageRegistry localImageRegistry; @Override public void createPartControl(Composite parent) { // 初始化本地注册表 localImageRegistry = new ImageRegistry(Display.getCurrent()); localImageRegistry.put(ControlVerifierToolTip.HEADER_CLOSE_ICON, ImageDescriptor.createFromFile(ControlsVerifierView.class, CLOSE_PNG)); // 后续使用本地注册表获取图标 Image closeIcon = localImageRegistry.get(ControlVerifierToolTip.HEADER_CLOSE_ICON); } @Override public void dispose() { // 销毁时清理本地注册表,避免内存泄漏 if (localImageRegistry != null) { localImageRegistry.dispose(); } super.dispose(); }
这种方式适合每个标签页需要独立管理资源的场景,但要记得在控件销毁时调用dispose释放资源。
内容的提问来源于stack exchange,提问作者Maana
相关产品推荐
相关产品推荐

