正如标题所述,我注意到每次重新启动组件时,都会重新下载使用<img>
标签加载的远程托管图像。单元的内容看起来像<html><img src="http://www.example.com/image.png"></html>
通常,这并不是什么大的问题时间是重新粉刷组件),并且可能是任何差的文件服务器托管图像的请求垃圾邮件/bandwith问题。
是否有可能说服秋千首次仅在需要时下载图像,然后在重新粉刷时重新使用缓存的副本,而不是每次重新下载?
和澄清,我注意到这种行为的方式是:
- 在呈现大图时迅速重新粉刷JTable单元时,请注意清晰的性能下降。
- 在Netty文件服务器上托管所述图像文件,并看到控制台输出如下:该页面的页面和页面随着组件的重新粉刷而迅速出现
编辑,在问题上添加mcve:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class Main {
public static void main(String[] argv) {
JFrame demoFrame = new JFrame("Table");
JTable jTable = new JTable();
demoFrame.getContentPane().add(new JScrollPane(jTable));
DefaultTableModel dtm = new DefaultTableModel(new Object[]{"cache test"}, 5);
jTable.setModel(dtm);
jTable.setValueAt("<html><img src="https://i.imgur.com/zfa0mEn.png"></html>", 2, 0);
demoFrame.pack();
demoFrame.setVisible(true);
}
}
也有点乏味和过度,也可以在某种形式的文件服务器中跟踪此处的文件请求,所以我已经决定反对。
我找到了一种解决问题的方法,可能不是最漂亮的,但它确实解决了性能问题和同一图像的不必要的垃圾邮件。
以下代码同时包含MCVE和TableModelListener
实现,该实现将自动检测到何时将图像标签放入任何JTable单元格的内容中,并将局部下载到应用程序工作目录上创建的文件夹,以及然后替换标签的SRC属性指向该缓存文件。
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
public class Main {
public static void main(String[] argv) {
JFrame demoFrame = new JFrame("Table");
JTable jTable = new JTable();
demoFrame.getContentPane().add(new JScrollPane(jTable));
DefaultTableModel dtm = new DefaultTableModel(new Object[]{"cache test"}, 5);
jTable.setModel(dtm);
jTable.getModel().addTableModelListener(new ImageCachingTableModelListener());
jTable.setValueAt("<html><img src="https://i.imgur.com/zfa0mEn.png"></html>", 2, 0);
demoFrame.pack();
demoFrame.setVisible(true);
}
private static class ImageCachingTableModelListener implements TableModelListener {
String regex = "<html>(?:[\s\S]*)<img(?:[\s\S]*)src="((?:[\S]+)\/([\S]+\.[A-Za-z0-9_-]+)(?:[\s\S]*))"(?:[\s\S]*)?>(?:[\s\S]*)<\/html>";
Pattern pattern = Pattern.compile(regex);
@Override
public void tableChanged(TableModelEvent evt) {
DefaultTableModel evtTableModel = (DefaultTableModel) evt.getSource();
if (evt.getType() == TableModelEvent.UPDATE) {
for (int i = evt.getFirstRow(); i <= evt.getLastRow(); i++) {
String content = (String) evtTableModel.getValueAt(i, evt.getColumn());
Matcher m = pattern.matcher(content);
if (m.find()) {
String imageSrc = m.group(1);
String imageFileName = m.group(2);
try (InputStream in = new URL(imageSrc).openStream()) {
File cacheDir = new File(System.getProperty("user.dir") + File.separator + "imgcache");
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
Path cachedFilePath = Paths.get(cacheDir.getCanonicalPath() + File.separator + imageFileName);
Files.copy(in, cachedFilePath, StandardCopyOption.REPLACE_EXISTING);
evtTableModel.setValueAt(content.replace(imageSrc, "file:" + cachedFilePath.toString()), i, evt.getColumn());
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
}
}
感谢您的帮助,希望这对别人有用。谢谢Artemis在代码的正则一部分方面提供帮助。