最近用SWING做一个类似网页图片展示的程序,图片展示是用JLabel,但是由于一次加载多张图片,如果图片数目过大,一次加载后内存的占用率会随着图片的增多一下猛增。
所以思考后,我用动态加载方法来加载图片组件,一次加载2M左右的图片,当JScrollBar滑动到接近尾部时,再加载下一个2M大小的图片集合。这个思想在某些网站上有所应用,我将之改造用在SWING程序中。
动态加载的核心思想就是需要监听JScrollBar的滚动轴。详细代码如下:
用于图片存放的JPanel
package com.wq.ui; import com.wq.cache.ListCache; import com.wq.util.LightLog; import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Created with IntelliJ IDEA. * User: wangq * Date: 12-8-2 * Time: 下午4:02 * 图床 ,对JAVA6.0,它支持得图象格式有[BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif] */ public class ViewContentPanel extends JPanel implements Page { private static ViewContentPanel ourInstance; private static LightLog logger = LightLog.getInstance(ViewContentPanel.class); private List<String> lastList = new ArrayList<String>(); //存储未显示的图片 public static ViewContentPanel getInstance() { if (ourInstance == null) { ourInstance = new ViewContentPanel(); } return ourInstance; } private ViewContentPanel() { constructPlate(); constructPage(); } @Override public void constructPlate() { this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); this.add(Box.createRigidArea(new Dimension(10, 10))); //构造一个指定长宽的二维Rigid组件。 } @Override public void constructPage() { Map<String, java.util.List<String>> map = ListCache.getInstance().getMenu(); int flag = 0; for (Map.Entry<String, java.util.List<String>> entry : map.entrySet()) { if (flag == 0) { java.util.List<String> list = entry.getValue(); this.addPic(list); } else break; flag++; } addPanelListener(); } private void addPanelListener() { this.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0 && !e.isControlDown() && !e.isShiftDown()) { ViewPanelMenu.getInstance().show(ViewContentPanel.getInstance(), e.getX(), e.getY()); //右键菜单显示 } } }); } public void addPic(List<String> list) { if (list == null) return; Long length = 0L; lastList.clear(); for (final String path : list) { File file = new File(path); if (!file.exists()) continue; if (length == 0L || length < 1024 * 2) { //显示最大2M的数据 length = length + file.length() / 1024; dealPic(path); logger.debug("添加图片" + path); } else { lastList.add(path); } } this.validate(); } public void clear() { this.removeAll(); constructPlate(); } private void dealPic(final String path) { final JLabel jLabel = new JLabel(new ImageIcon(path)); jLabel.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0 && !e.isControlDown() && !e.isShiftDown()) { PicMenu.getInstance().show(jLabel, e.getX(), e.getY()); PicMenu.getInstance().setFilePath(path); } } }); this.add(jLabel); this.add(Box.createVerticalStrut(7)); } /** * 用于动态加载图片 */ public void loadNextPic() { if (!lastList.isEmpty()) { List<String> temList = new ArrayList<String>(); temList.addAll(lastList); addPic(temList); } } }
其中lastList中存放的是未加载到页面上的图片路径,当lastList为空时,所有的图片才全部加载到页面上。
滚动容器JScrollPane 滚动轴监听代码如下
final JScrollBar jScrollBar = this.getVerticalScrollBar(); jScrollBar.addAdjustmentListener(new AdjustmentListener() { private int height = 0; @Override public void adjustmentValueChanged(AdjustmentEvent e) { int cur = jScrollBar.getValue(); int max = jScrollBar.getMaximum(); if ((cur - height > 3500) && (max - cur) < 1800) { System.out.println("开始加载新图片..........................."); ViewContentPanel.getInstance().loadNextPic(); ViewPanel.getInstance().updateUI(); height = cur; } } });
这里监听了JSrollBar的滚动轴,当滚动轴接近尾部时,调用加载方法,剩余的图片,将陆续被加载。
稍后我将会将整个程序放上来供大家参考。