假设我们有一个名为
的URL“mysite.com”
在这个网站中,我们有一个名为images的目录,其中包含大约200张.PNG图片
我想制作一个程序,逐个扫描这些图片(如果你知道上一张图片的URL,你可以预测图片的URL),然后我想在我的JFrame上显示这个图片
我最初想到的是,因为我知道网址,为什么我不扫描所有不同的图片网址,然后执行此操作?
Image image = ImageIO.read(url); hasImage.setIcon(new
ImageIcon(image));
现在
hasImage
是一个JLabel,我使用刚从URL下载的图像
和
url
是类URL的对象
所以,每次在循环中我都会找到新的URL,并且我调用了上面刚刚发布的2行代码的函数,以便更新标签上的图像
请注意,这两行都在ActionListener按钮内,因此每次单击按钮时,都会显示下一个图像
这里有一个主要问题。
当我想要显示下一个图像时,需要一些时间来创建新的url对象,下载图像,然后将其显示在我的标签上,这有点烦人,特别是如果你匆忙并且想要快速显示图像...
现在,我想到了另一个实现,为什么不下载所有图像,将它们保存在本地某处,然后扫描存储图像的目录,并在每次单击按钮时显示它们?
好的,我这样做了,但问题是下载所有图片需要一分多钟 之后它运作顺利,非常快
所以这里最大的问题是它需要花费很多时间来下载图像,所以它基本上是以前的实现,但是在这一次而不是等待我按下按钮时,我等待一切下载,这需要相同的时间......
我的问题是,我怎样才能让它更快?如果它会在不到5秒的时间内下载所有图像,我会满意
这是我正在使用的功能,以保存图像
private void saveImages() {
Image image;
int ID = 1;
String destFile = "destFolder" + ID + ".png";
try {
image = ImageIO.read(url);
ImageIO.write((RenderedImage) image, "png", new File(destFile));
} catch (IOException ex) {
}
while (ID < 200) {
try {
String path = url.getPath();
String[] token = path.split("-");
String[] finalToken = token[2].split("\\.");
ID = Integer.parseInt(finalToken[0]);
url = new URL("http://somesite/images/" + (ID + 1) + ".png");
destFile = "C:\\...\\destFolder\\" + ID + ".png";
image = ImageIO.read(url);
ImageIO.write((RenderedImage) image, "png", new File(destFile));
} catch (MalformedURLException ex) {
JOptionPane.showMessageDialog(null,
"URL is not in the correct form", "Malformed URL",
JOptionPane.ERROR_MESSAGE);
} catch (IOException ex) {
}
}
JOptionPane.showMessageDialog(null, "Images were loaded successfully",
"Success", JOptionPane.INFORMATION_MESSAGE);
}
编辑:顺便说一下,我真的很抱歉代码,它有点乱,这只是我输入的第一件事....我会稍后改进它但我希望你能理解我遇到的问题我正面对现在:)
答案 0 :(得分:3)
Java或实现都不是问题,而是连接的速度。您可以下载应用程序所需的所有图像(这需要一些时间,如果没有查看图像则毫无意义),或者在点击它们时加载它们。
如果您想让它看起来更快一点,您可以开始将图像加载到本地数据库或文件系统(如缓存)。这显然有其缺点,因为一旦图片加载一次,它只会使加载时间更快,并且通常理想的是没有非常大的缓存。
只需查看一张图片,您还可以加载五张左右的下一张和上一张图片,这样可以让用户感觉更快。
答案 1 :(得分:1)
从网络下载200张图片总是需要一些时间。你需要做些什么才能加快速度呢
答案 2 :(得分:0)
我建议您在后台加载图片,并在加载后立即显示图片,这样您的用户界面就会响应。当您转到特定图像时,您也可以自动加载下一个图像。
这是一个相当绿色的干编码(实际上没有尝试编译)尝试,这应该证明这个想法。 (原谅紧密耦合,而不是在类中捣乱责任。而且,它对于imageBuffer
的无限性而言更加傲慢,并且没有卸载到磁盘上。
class ImageManager {
private ExecutorService asyncLoader = Executors.newFixedThreadPool(2);
private HashMap<Integer, Image> imageBuffer = new HashMap<Integer, Image>();
private final int PRELOAD = 2;
private String baseUrl;
public ImageManager(String baseUrl) {
this.baseUrl = baseUrl;
}
public void loadImageAndUpdateLabel(final int idx, final JLabel label) {
asyncLoader.execute(new Runnable() {
public void run() {
loadSync(idx);
SwingUtilities.invokeLater(new Runnable() {
label.setIcon(new ImageIcon(imageBuffer.get(idx)));
label.setText(null);
});
}
});
triggerAsyncPreload(idx);
}
public void triggerAsyncPreload(int idx) {
for (int i=idx-PRELOAD; i<idx+PRELOAD; i++) {
if (i>0) {
loadAsync(i);
}
}
}
public synchronized void loadSync(int idx) {
if (imageBuffer.get(idx) == null) {
imageBuffer.put(idx, ImageIO.read(new URL(baseUrl, idx+".png")));
}
}
public void loadAsync(final int idx) {
asyncLoader.execute(new Runnable() {
public void run() {
loadSync(idx);
}
});
}
}
class ... {
...
private int currentImageIdx = 0;
private ImageManager imageManager = new ImageManager("http://site.com/images/");
private JLabel label = new JLabel();
private JButton nextImageButton = new JButton(new AbstractAction("Next image") {
public void actionPerformed(ActionEvent e) {
currentImageIdx++;
label.setIcon(null);
label.setText("Loading image "+currentImageIdx);
imageManager.loadImageAndUpdateLabel(currentImageIdx, label);
}
});
...
}