本文共 5656 字,大约阅读时间需要 18 分钟。
本文出自
package com.zsd;import java.awt.Component;import java.awt.Graphics;import java.net.URL;import javax.swing.Icon;import javax.swing.ImageIcon;//实现Icon接口public class ImageProxy implements Icon { ImageIcon imageIcon; URL imageURL; Thread retrievalThread; boolean retrieving = false; // 将图片的URL传入构造器中 public ImageProxy(URL url) { imageURL = url; } // 在图像加载完毕前,返回默认的宽和高 // 图像加载完毕后,装给iamgeIcon处理 public int getIconWidth() { if (imageIcon != null) { return imageIcon.getIconWidth(); } else { return 800; } } public int getIconHeight() { if (imageIcon != null) { return imageIcon.getIconHeight(); } else { return 600; } } // 当要在屏幕上绘制图像时,就调用此方法 public void paintIcon(final Component c, Graphics g, int x, int y) { // 如果已经有了icon,就画出 if (imageIcon != null) { imageIcon.paintIcon(c, g, x, y); } else { // 还没有icon时,就显示“加载中...”的消息 g.drawString("CD封面加载中,请稍后...", x + 300, y + 190); if (!retrieving) { retrieving = true; // 在这个线程中加载真正的icon图像。注意,加载图像和ImageIcon是同步(synchronous) // 也就是说,只有在加载完之后,ImageIcon构造器才会返回。这样,我们的程序会耗在这里 // 所以要把加载变成异步(asynchronous)的。 retrievalThread = new Thread(new Runnable() { public void run() { try { imageIcon = new ImageIcon(imageURL, "CD Cover"); c.repaint(); } catch (Exception e) { e.printStackTrace(); } } }); retrievalThread.start(); } } }}
package com.zsd;import java.awt.*;import javax.swing.*;class ImageComponent extends JComponent { private Icon icon; public ImageComponent(Icon icon) { this.icon = icon; } public void setIcon(Icon icon) { this.icon = icon; } public void paintComponent(Graphics g) { super.paintComponent(g); int w = icon.getIconWidth(); int h = icon.getIconHeight(); int x = (800 - w)/2; int y = (600 - h)/2; icon.paintIcon(this, g, x, y); }}
package com.zsd;import java.net.*;import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.util.*;public class ImageProxyTestDrive { ImageComponent imageComponent; JFrame frame = new JFrame("CD封面加载器"); JMenuBar menuBar; // 菜单栏 JMenu menu; // 菜单 Hashtable cds = new Hashtable(); public static void main (String[] args) throws Exception { ImageProxyTestDrive testDrive = new ImageProxyTestDrive(); } public ImageProxyTestDrive() throws Exception{ // 构造菜单项用的, key=CD名, value=URL cds.put("三国志:英雄的黎明","http://img3.douban.com/lpic/s4131026.jpg"); cds.put("东邪西毒","http://img3.douban.com/lpic/s10425517.jpg"); cds.put("龙猫","http://img3.douban.com/lpic/s1668213.jpg"); cds.put("Once <曾经> ","http://img3.douban.com/lpic/s2821080.jpg"); cds.put("太阳照常升起","http://img3.douban.com/lpic/s4714977.jpg"); cds.put("蝙蝠侠:侠影之谜","http://img3.douban.com/lpic/s4591642.jpg"); cds.put("天国王朝","http://img3.douban.com/lpic/s2595263.jpg"); // 设置初始的CD封面 URL initialURL = new URL((String)cds.get("Once <曾经> ")); // 建立菜单栏 menuBar = new JMenuBar(); menu = new JMenu("最爱的CD"); menuBar.add(menu); frame.setJMenuBar(menuBar); for(Enumeration e = cds.keys(); e.hasMoreElements();) { String name = (String)e.nextElement(); JMenuItem menuItem = new JMenuItem(name); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { imageComponent.setIcon(new ImageProxy(getCDUrl(event.getActionCommand()))); frame.repaint(); } }); } // set up frame and menus Icon icon = new ImageProxy(initialURL); imageComponent = new ImageComponent(icon); frame.getContentPane().add(imageComponent); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(800,600); frame.setVisible(true); } URL getCDUrl(String name) { try { return new URL((String)cds.get(name)); } catch (MalformedURLException e) { e.printStackTrace(); return null; } }} 曾经> 曾经>
现在再来回顾虚拟代理的定义,虚拟代理为什么取名为“虚拟”代理呢?以这个CD封面下载器为例,CD浏览器真正需要的是一个ImageIcon也就是封面图片并要让它显示出来,但是由于图片还在网上不存在本地,所以就用了一个代理ImageProxy来假装就是“ImageIcon”,对于CD浏览器来说,他把这个代理看作和一般的图片一样,让他显示出来。但是刚创建代理Imageproxy时,这个代理根本就没有图片!所以说他是“虚拟”的,挂了个马甲装自己就是图片!一直到下载完图片之后,才真正地把图片显示出来。