protected void setImageFromScout(String imageId, Object image) { if (image == null) { if (imageId != null) { // try to use uncached image image = getUncachedIconLocator().getImage(imageId); if (image == null) { // as fallback, use cached image image = getSwingEnvironment().getImage(imageId); } } } getSwingImageViewer().setImage(image); }
private SwingUncachedIconLocator m_uncachedIconLocator; protected SwingUncachedIconLocator getUncachedIconLocator() { if (m_uncachedIconLocator == null) { m_uncachedIconLocator = new SwingUncachedIconLocator(getSwingEnvironment().getScoutSession().getIconLocator()); } return m_uncachedIconLocator; }
public Image getImage(String name) { if (name == null || AbstractIcons.Null.equals(name) || name.length() == 0) { return null; } Image img; synchronized (m_cacheLock) { //img = m_imagesByNameCache.get(name); // not using cache //if (img == null && !m_imagesByNameCache.containsKey(name)) { // not using cache img = createImageImpl(name); if (img == null) { img = autoCreateMissingImage(name); } //m_imagesByNameCache.put(name, img); // not using cache if (LOG.isDebugEnabled()) { LOG.debug("load image '" + name + "' as " + img); } if (img == null) { warnImageNotFound(name); } //} // not using cache } return img; }
<formField active="true" modelClass="com.bsiag.minicrm.client.ui.form.fields.ext.IUncachedImageField" name="Uncached Image Field" scope="default"> <uiClass class="com.bsiag.minicrm.ui.swing.form.fields.ext.SwingScoutUncachedImageField"> </uiClass> </formField>
The tutorial basically seems to read the image data and then put it in the icon cache from which it can be retrieved by the string id. So maybe it was designed to cache the icon and never change it again.
Have you tried reading the image data (= byte[]) by yourself and directly setting it into the ImageField by using the method setImage(Object)?
This does not work for images in a table, though, because the ImageField is not used there. For an ICell, you can only specify icons "by ID" and not "by data". IDs are then resolved using the SwingEnvironment's icon locator. So, if you override the method createIconLocator() and provide your own (non-caching) SwingIconLocator, you should be able to achieve the desired behavior. As far as I could see at a quick glance, the ImageField also retrieves the icon locator from the SwingEnvironment. If you try that our, please let us know if it worked.
Regarding your concern about having to copy so many files the create a custom widget: I admit that I did not try it out ( ), but I think in your case it would have to be sufficient to only register a new UncachedSwingScoutImageField class that extends SwingScoutImageField (for 'IImageField'). If I am correct, the most specific (i.e. greatest distance to IFormField) class "wins". Duplicating the model class (AbstractImageField) should not be necessary as you do not want to alter the model behavior.
(Note that this approach would then affect all ImageField!)
Does that already help your for your problem? If you think that a mechanism to invalidate the image cache is missing from Scout, maybe we should discuss it further.
public class SwingScoutUncachedImageField extends SwingScoutImageField { private SwingUncachedIconLocator m_uncachedIconLocator; protected SwingUncachedIconLocator getUncachedIconLocator() { if (m_uncachedIconLocator == null) { m_uncachedIconLocator = new SwingUncachedIconLocator(getSwingEnvironment().getScoutSession().getIconLocator()); } return m_uncachedIconLocator; } @Override protected void setImageFromScout(String imageId, Object image) { if (image == null) { if (imageId != null) { // try to use uncached image image = getUncachedIconLocator().getImage(imageId); if (image == null) { // as fallback, use cached image image = getSwingEnvironment().getImage(imageId); } } } getSwingImageViewer().setImage(image); }
<formField active="true" modelClass="org.eclipse.scout.rt.client.ui.form.fields.imagebox.IImageField" name="Uncached Image Field" scope="default"> <uiClass class="com.bsiag.minicrm.ui.swing.form.fields.ext.SwingScoutUncachedImageField"> </uiClass> </formField>
This should make my new class the "most distant" for this interface but it seems that this does not work, the setImageFromScout() method was always called on SwingScoutImageField and not on my class. Removing the plugin entry doesn't make a difference.
I don't know if you have any further ideas on this.
@Override public ISwingScoutFormField<?> createFormField(JComponent parent, IFormField field) { if (field instanceof IImageField /* && add further conditions here */) { SwingScoutUncachedImageField ui = new SwingScoutUncachedImageField(); ui.createField((IImageField) field, this); decorate(field, ui); return ui; } return super.createFormField(parent, field); }
Overall I think using the MD5 hash as imageId for the table cells and directly using the setImage() method on the form will be the most efficient way to deal with my requirement.
Hi, I am facing the same issue now. I would like to display image which will constantly change. but the image is cached. I am using rap client and swt client. do I need to modify SwtEnvironment to make it not cache image?
(...) Unlike the FontRegistry, it is an error to replace images. As a result there are no events that fire when values are changed in the registry
If I using MD5 hash as cache value, will the image cache be released? or it will keep building up again and again and eventually hit too many handle in windows or too many open file in linux?
The other possibility would be to not delegate the creation of IImageField UI objects to the FormFieldFactory, but build them yourself in your own SwingEnvironment:
@Override public ISwingScoutFormField<?> createFormField(JComponent parent, IFormField field) { if (field instanceof IImageField /* && add further conditions here */) { SwingScoutUncachedImageField ui = new SwingScoutUncachedImageField(); ui.createField((IImageField) field, this); decorate(field, ui); return ui; } return super.createFormField(parent, field); }
Urs Beeli wrote on Thu, 20 December 2012 04:47Overall I think using the MD5 hash as imageId for the table cells and directly using the setImage() method on the form will be the most efficient way to deal with my requirement.
I like the idea of using the MD5 hash as a cache value. Looks promising! Thanks for sharing.