I'm taking Pattern Oriented Software Architecture for Concurrent and Networked Software course on Coursera now. And I've decided to practice a bit, namely to apply Proxy pattern for a real program. Namely, here's my goal:
1. I have a GUI program which consists of a JButton and JLabel
2. When the user clicks a button, an image is downloaded from the internet and placed as an icon of JLabel
I want to implement it using a Proxy pattern. Namely, I create a proxy class, who implements Icon interface and loads an image on demand. Here's the code:
public class NetIcon implements Icon { private URL location; private ImageIcon image; public NetIcon(URL location){ this.location = location; } private void loadImage(){ try{ BufferedImage img = null; while(img == null) img = ImageIO.read(location); image = new ImageIcon(img); } catch(IOException ex){} } @Override public void paintIcon(Component c, Graphics g, int x, int y) { if(image == null) loadImage(); image.paintIcon(c, g, x, y); } @Override public int getIconWidth() { if(image != null) return image.getIconWidth(); return -1; } @Override public int getIconHeight() { if(image != null) return image.getIconHeight(); return -1; } }
But here are some difficulties. Namely, when I set an instance of NetIcon class as an Icon of a label and repaint it, GUI blocks because it's repainting takes too long (due to the necessity to download image). I want to indicate that the image is downloading with a gif-file on the label, but I can't do that. Here's the code (without gif-file, because I even have no idea where to put it's code...):
public static void main(String[] args) throws IOException, JSONException{ final JFrame f = createFrame(); final JLabel l = new JLabel("Picture"); f.add(l, BorderLayout.CENTER); JButton btn = new JButton("Load Image"); ActionListener btnActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try{ URL url = new URL("http://us.123rf.com/400wm/400/400/dixi_/dixi_1101/dixi_110100024/8669259-siberian-cat-isolated-on-white.jpg"); NetIcon ico = new NetIcon(url); l.setIcon(ico); //GUI blocks f.repaint(); //GUI unblocks } catch(IOException ex) {} } }; btn.addActionListener(btnActionListener); f.add(btn, BorderLayout.SOUTH); } private static JFrame createFrame() { JFrame result = new JFrame(); result.setBounds(200, 200, 300, 300); result.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); result.setVisible(true); return result; }
Where do I have architectural flaws? How can I improve this design?