首页 > 开发 > Java > 正文

Java Swing 多线程加载图片(保证顺序一致)

2024-07-13 10:14:43
字体:
来源:转载
供稿:网友

大二的时候做的课程设计,图片管理器,当时遇到图片很多的文件夹,加载顺序非常慢。虽然尝试用多个Thread加载图片,却无法保证图片按顺序加载。直到今天学会了使用Callable接口和Future接口,于是心血来潮实现了这个功能。

废话不多说,看代码。

多线程加载图片(核心):

package com.lin.imagemgr;import java.awt.Dimension;import java.awt.image.BufferedImage;import java.io.File;import java.io.FilenameFilter;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.stream.Collectors;import javax.swing.ImageIcon;import javax.swing.JLabel;import net.coobird.thumbnailator.Thumbnails;public class ImageMgr { private static ImageMgr instance = new ImageMgr(); private ImageMgr() {} public static ImageMgr getInstance() {  return instance; } //线程池 private ExecutorService executor = Executors.newFixedThreadPool(8); public List<JLabel> loadImages(String path) {  List<JLabel> images = new ArrayList<>();  File file = new File(path);  if (!file.isDirectory()) {   throw new RuntimeException("need directory!");  }  File[] files = file.listFiles(new FilenameFilter() {   @Override   public boolean accept(File dir, String name) {    //thumbnail只支持jpg??    if (name.endsWith(".jpg")) {     return true;    }    return false;   }  });  //并发加载图片,并使用Future保存加载结果  List<Future<MyLabel>> futures = new ArrayList<>();  for (final File f : files) {   Future<MyLabel> future = executor.submit(() -> {    return new MyLabel(f.getName(), f.getAbsolutePath());   });   futures.add(future);  }  //等待所有并发加载返回结果  try {   for (Future<MyLabel> future : futures) {    MyLabel icon = future.get();    images.add(icon);   }  } catch (InterruptedException e) {   e.printStackTrace();  } catch (ExecutionException e) {   e.printStackTrace();  }  //Java8使用stream API 进行排序  List<JLabel> sortedList = images.stream().sorted().collect(Collectors.toList());  return sortedList; } //继承JLabel并实现Comparable接口,从而对JLabel进行排序 private static class MyLabel extends JLabel implements Comparable<MyLabel>{  private static final long serialVersionUID = 1L;  private String fileName;  public MyLabel(String fileName, String fullPath) {   this.fileName = fileName;   //使用thumbnailator生成缩略图   try {    BufferedImage bufferedImage = Thumbnails.of(fullPath)     .size(100, 120)    .asBufferedImage();    setIcon(new ImageIcon(bufferedImage));    setPreferredSize(new Dimension(100, 120));   } catch (IOException e) {    e.printStackTrace();   }  }  @Override  public int compareTo(MyLabel o) {   int result = this.fileName.compareTo(o.fileName);   return result;  } }}

Swing界面:

 

package com.lin.imagemgr;import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.FlowLayout;import java.util.List;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextField;public class MainFrame extends JFrame{ private static final long serialVersionUID = 1L; private JTextField pathField; private JButton showBtn; private JPanel contentPanel; public void init() {  JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));  topPanel.setPreferredSize(new Dimension(800, 40));  pathField = new JTextField(50);  showBtn = new JButton("显示图片");  topPanel.add(pathField);  topPanel.add(showBtn);  getContentPane().add(BorderLayout.NORTH, topPanel);  contentPanel = new JPanel();  contentPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));  contentPanel.setPreferredSize(new Dimension(750, 1800));  JScrollPane jsp = new JScrollPane(contentPanel);  getContentPane().add(BorderLayout.CENTER, jsp);  showBtn.addActionListener((e) -> {   try {    loadImages();   } catch (Exception ex) {    ex.printStackTrace();   }  });  setSize(800, 650);  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  setLocationRelativeTo(null);  setVisible(true); } public void loadImages() {  contentPanel.removeAll();  String path = pathField.getText();  long start = System.currentTimeMillis();  List<JLabel> images = ImageMgr.getInstance().loadImages(path);  for (JLabel label :images) {   contentPanel.add(label);  }  contentPanel.updateUI();  long end = System.currentTimeMillis();  System.out.println("加载需要" + (end - start) + "毫秒!"); } public static void main(String[] args) {  new MainFrame().init(); }}

运行结果

Java,Swing,多线程,加载图片

Java,Swing,多线程,加载图片

在我的电脑上,加载92张图片并渲染到界面上,总共花了1568毫秒。大家可以找一个图片很多的文件夹,尝试加载大量图片的情况。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表