Когда JTextPane
видит тег <img>
, он проверяет, существует ли изображение в кэше, и если нет, он пытается прочитать изображение с URL-адреса.Библиотека html, используемая JTextPane
, не поддерживает данные изображения в кодировке base64 в теге <img>
, поэтому нам нужно будет сделать это по-другому.
Оказывается, мы можем вручную добавлять изображения вкеш изображений.Это может быть использовано, чтобы выбрать какой-то неверный URL и присвоить ему изображение.
Давайте добавим изображение в кеш и покажем его в JTextPane
!
Сначала вы хотитепреобразовать изображение в BufferedImage
.Это можно сделать с помощью класса ImageIO
.
byte[] imgBytes = decodeBase64(base64Code);
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgBytes));
Обратите внимание, что здесь нам нужны необработанные байты изображения, а не кодировка base64.Если вы читаете изображение из файла, вы можете передать File
в функцию read
вместо входного потока.
Теперь, когда у нас есть изображениекак BufferedImage
, мы можем написать функцию, которая добавляет ее в кеш.
@SuppressWarnings({ "rawtypes", "unchecked" })
public static String saveImageToCache(JTextPane pane, BufferedImage img, String name) throws MalformedURLException {
Dictionary cache = (Dictionary) pane.getDocument().getProperty("imageCache");
if (cache == null) {
// No cache exists, so create a new one.
cache = new Hashtable();
pane.getDocument().putProperty("imageCache", cache);
}
String url = "http:\\buffered/" + name;
cache.put(new URL(url), img);
return url;
}
Обратите внимание, что я подавляю некоторые предупреждения о параметрах типа в Dictionary
и Hashtable
.Обычно этого следует избегать, но в этом случае мы имеем дело с бессмыслицей Swing таким образом, чтобы можно было подавлять предупреждения.
Этот метод по сути выбирает некоторый недействительный URL-адрес и сохраняет изображение по этому URL-адресу.
Обратите внимание на аргумент name
.Это будет частью URL, и если вы попытаетесь сохранить изображение в кэш с тем же именем, что и у предыдущего изображения, это заменит это предыдущее изображение.Избегайте использования сумасшедших символов в этом имени, так как new Url(url)
может выдать MalformedURLException
, если это недопустимый URL.
Теперь мы можем использовать его с JTextPane
.
BufferedImage img = ...;
JTextPane pane = new JTextPane();
pane.setContentType("text/html");
String url = saveImageToCache(pane, img, "image1");
pane.setText("<html><body><img src=\"" + url + "\"></body></html>");
JFrame frame = new JFrame("image test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pane);
frame.setSize(img.getWidth(), img.getHeight());
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Обратите внимание, что перед добавлением изображения в кэш необходимо вызвать setContentType
, так как метод очищает кэш.Кроме того, важно, чтобы изображение было добавлено в кэш до вызова setText
, чтобы гарантировать, что изображения будут добавлены до того, как это понадобится Swing.
Если изображение в кэше изменяется с помощью saveImageToCache
сранее известное имя, вам нужно каким-то образом обновить JTextPane
, например, позвонив по номеру setText
.
Если у вас много изображений, вы можете удалить их изкеш, когда они больше не нужны, чтобы избежать чрезмерного использования памяти.Один из способов сделать это - определить функцию, как показано ниже, которая удаляет изображение из кэша.
@SuppressWarnings({ "rawtypes" })
public static void removeImageFromCache(JTextPane pane, String name) throws MalformedURLException {
Dictionary cache = (Dictionary) pane.getDocument().getProperty("imageCache");
if (cache == null) {
// There is no cache, so the image is not in the cache.
return;
}
String url = "http:\\buffered/" + name;
cache.remove(new URL(url));
}
Вы также можете очистить кэш, вызвав setContentType
или заменив JTextPane
с новым объектом.Это работает, поскольку кеш хранится в JTextPane
.