Advertisement
Guest User

Untitled

a guest
Oct 31st, 2014
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.78 KB | None | 0 0
  1. // For week 8
  2. // sestoft@itu.dk * 2014-10-12
  3.  
  4. // General GUI stuff
  5. import java.awt.*;
  6. import java.awt.event.*;
  7. import javax.swing.*;
  8.  
  9. // For the SwingWorker subclass
  10. import java.util.List;
  11. import java.util.concurrent.CancellationException;
  12. import java.util.concurrent.ExecutionException;
  13. import java.util.concurrent.atomic.AtomicInteger;
  14.  
  15. // For downloading web pages
  16. import java.net.URL;
  17. import java.io.BufferedReader;
  18. import java.io.InputStreamReader;
  19. import java.io.IOException;
  20.  
  21. // For communicating with the progress bar
  22. import java.beans.PropertyChangeEvent;
  23. import java.beans.PropertyChangeListener;
  24.  
  25. public class TestFetchWebGui {
  26.   public static void main(String[] args) {
  27.     // badFetch();
  28.     goodFetch();
  29.   }
  30.  
  31.   // (0) This version performs all the slow web access work on the
  32.   // event thread.  This means that the GUI remains blocked until all
  33.   // pages have been fetched, so the Cancel button can have no effect
  34.   // (even if it were connected to something) and the text area does
  35.   // not get repainted and hence not updated with the results as they
  36.   // become available.
  37.  
  38.   private static void badFetch() {
  39.     final JFrame frame = new JFrame("TestFetchWebGui");
  40.     final JPanel outerPanel = new JPanel(),
  41.       buttonPanel = new JPanel();
  42.     final JButton fetchButton = new JButton("Fetch"),
  43.       cancelButton = new JButton("Cancel");
  44.     frame.add(outerPanel);
  45.     outerPanel.setLayout(new BorderLayout());
  46.     buttonPanel.setLayout(new GridLayout(2, 1));
  47.     buttonPanel.add(fetchButton);
  48.     buttonPanel.add(cancelButton);
  49.     outerPanel.add(buttonPanel, BorderLayout.EAST);
  50.     final TextArea textArea = new TextArea(25, 80);
  51.     textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
  52.     outerPanel.add(textArea, BorderLayout.WEST);
  53.     fetchButton.addActionListener(new ActionListener() {
  54.         public void actionPerformed(ActionEvent e) {
  55.           for (String url : urls) {
  56.             System.out.println("Fetching " + url);
  57.             String page = getPage(url, 200);
  58.             textArea.append(String.format("%-40s%7d%n", url, page.length()));
  59.           }
  60.         }});
  61.     frame.pack(); frame.setVisible(true);
  62.   }
  63.  
  64.   // (1) Use a SwingWorker subclass to perform the work in the
  65.   // doInBackground method on a different thread, cause the event
  66.   // thread to show the final result using the done method.  (2) Add a
  67.   // progress bar that displays the fraction of web pages fetched so
  68.   // far.  (3) Add the possibility of cancellation by testing
  69.   // isCancelled() in the doInBackground method, and catch the
  70.   // CancellationException in the done method.  (4) Display the
  71.   // results as they become available by letting doInBackground call
  72.   // the publish method, which will cause the event thread to sooner
  73.   // or later run the process method.  In this case the done method
  74.   // should not also write the results to the textArea.  Note that it
  75.   // would be illegal for the worker thread to directly .append to the
  76.   // textArea.
  77.  
  78.   private static void goodFetch() {
  79.     final JFrame frame = new JFrame("TestFetchWebGui");
  80.     final JPanel outerPanel = new JPanel(),
  81.       buttonPanel = new JPanel();
  82.     final JButton fetchButton = new JButton("Fetch"),
  83.       cancelButton = new JButton("Cancel");
  84.     frame.add(outerPanel);
  85.     outerPanel.setLayout(new BorderLayout());
  86.     buttonPanel.setLayout(new GridLayout(2, 1));
  87.     buttonPanel.add(fetchButton);
  88.     buttonPanel.add(cancelButton);
  89.     outerPanel.add(buttonPanel, BorderLayout.EAST);
  90.     final TextArea textArea = new TextArea(25, 80);
  91.     textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
  92.     outerPanel.add(textArea, BorderLayout.WEST);
  93.     // (1) Use a background thread, not the event thread, for work
  94.     DownloadWorker downloadTask = new DownloadWorker(textArea);
  95.     fetchButton.addActionListener(new ActionListener() {
  96.         public void actionPerformed(ActionEvent e) {
  97.           downloadTask.execute();
  98.         }});
  99.     // (2) Add a progress bar
  100.     JProgressBar progressBar = new JProgressBar(0, 100);
  101.     outerPanel.add(progressBar, BorderLayout.SOUTH);
  102.     downloadTask.addPropertyChangeListener(new PropertyChangeListener() {
  103.         public void propertyChange(PropertyChangeEvent e) {
  104.           if ("progress".equals(e.getPropertyName())) {
  105.             progressBar.setValue((Integer)e.getNewValue());
  106.           }}});
  107.     // (3) Enable cancellation
  108.     cancelButton.addActionListener(new ActionListener() {
  109.         public void actionPerformed(ActionEvent e) {
  110.           downloadTask.cancelAll();
  111.         }});
  112.     frame.pack(); frame.setVisible(true);
  113.   }
  114.  
  115.   private static final String[] urls =
  116.   { "http://www.itu.dk", "http://www.di.ku.dk", "http://www.miele.de",
  117.     "http://www.microsoft.com", "http://www.amazon.com", "http://www.dr.dk",
  118.     "http://www.vg.no", "http://www.tv2.dk", "http://www.google.com",
  119.     "http://www.ing.dk", "http://www.dtu.dk", "http://www.eb.dk",
  120.     "http://www.nytimes.com", "http://www.guardian.co.uk", "http://www.lemonde.fr",  
  121.     "http://www.welt.de", "http://www.dn.se", "http://www.heise.de", "http://www.wsj.com",
  122.     "http://www.bbc.co.uk", "http://www.dsb.dk", "http://www.bmw.com", "https://www.cia.gov"
  123.   };
  124.  
  125.   public static String getPage(String url, int maxLines) {
  126.     try {
  127.       // This will close the streams after use (JLS 8 para 14.20.3):
  128.       try (BufferedReader in
  129.            = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) {
  130.         StringBuilder sb = new StringBuilder();
  131.         for (int i=0; i<maxLines; i++) {
  132.           String inputLine = in.readLine();
  133.           if (inputLine == null)
  134.             break;
  135.           else
  136.             sb.append(inputLine).append("\n");
  137.         }
  138.     return sb.toString();
  139.       }
  140.     } catch (IOException exn) {
  141.       System.out.println(exn);
  142.       return "";
  143.     }
  144.   }
  145.  
  146.   static class DownloadWorker extends SwingWorker<String,String> {
  147.     private final TextArea textArea;
  148.     private final SingleDownloadWorker[] downloaders;
  149.     public static final AtomicInteger atomicProgress = new AtomicInteger(0);
  150.  
  151.     public DownloadWorker(TextArea textArea) {
  152.       this.textArea = textArea;
  153.       downloaders = new SingleDownloadWorker[urls.length];
  154.     }
  155.  
  156.     public void cancelAll() {
  157.       for(int i = 0; i < downloaders.length; i++) {
  158.         downloaders[i].cancel(true);
  159.       }
  160.       this.cancel(false);
  161.     }
  162.  
  163.     // Called on a separate worker thread, not the event thread, and
  164.     // hence cannot write to textArea.
  165.     public String doInBackground() {
  166.       // StringBuilder sb = new StringBuilder();
  167.       // int count = 0;
  168.       // for (String url : urls) {
  169.       //   if (isCancelled())
  170.       //     break;
  171.       //   System.out.println("Fetching " + url);
  172.       //   String page = getPage(url, 200),
  173.       //     result = String.format("%-40s%7d%n", url, page.length());
  174.       //   // sb.append(result); // (1)
  175.       //   setProgress((100 * ++count) / urls.length); // (2)
  176.       //   publish(result); // (4)
  177.       // }
  178.       // return sb.toString();
  179.       for(int i = 0; i < urls.length; i++) {
  180.         if(isCancelled())
  181.           break;
  182.         downloaders[i] = new SingleDownloadWorker(textArea, urls[i], this);
  183.       }
  184.       for(SingleDownloadWorker s : downloaders)
  185.         s.execute();
  186.       return "";
  187.     }
  188.  
  189.     // (4) Called on the event thread to process results previously
  190.     // published by calls to the publish method.
  191.     public void process(List<String> results) {
  192.       for (String result : results)
  193.         textArea.append(result);
  194.     }
  195.  
  196.     // Called in the event thread when done() has terminated, whether
  197.     // by completing or by being cancelled.
  198.     public void done() {
  199.       try {
  200.         textArea.append(get());
  201.         textArea.append("Done");
  202.       } catch (InterruptedException exn) { }
  203.         catch (ExecutionException exn) { throw new RuntimeException(exn.getCause()); }
  204.         catch (CancellationException exn) { textArea.append("Cancelled"); }  // (3)
  205.     }
  206.  
  207.     public void updateProgress() {
  208.       setProgress(atomicProgress.getAndAdd(100/urls.length));
  209.     }
  210.   }
  211.  
  212.   static class SingleDownloadWorker extends SwingWorker<String,String> {
  213.     private final TextArea textArea;
  214.     private final String url;
  215.     private final DownloadWorker parent;
  216.  
  217.     public SingleDownloadWorker(TextArea textArea, String url, DownloadWorker parent) {
  218.       this.textArea = textArea;
  219.       this.url = url;
  220.       this.parent = parent;
  221.     }
  222.  
  223.     // Called on a separate worker thread, not the event thread, and
  224.     // hence cannot write to textArea.
  225.     public String doInBackground() {
  226.       StringBuilder sb = new StringBuilder();
  227.       //int count = 0;
  228.       System.out.println("Fetching " + url);
  229.       String page = getPage(url, 200),
  230.         result = String.format("%-40s%7d%n", url, page.length());
  231.       // sb.append(result); // (1)
  232.       //setProgress((100 * ++count) / urls.length); // (2)
  233.       //parent.setProgress(DownloadWorker.atomicProgress.getAndAdd(1/urls.length));
  234.       parent.updateProgress();
  235.       publish(result); // (4)
  236.       return sb.toString();
  237.     }
  238.  
  239.     // (4) Called on the event thread to process results previously
  240.     // published by calls to the publish method.
  241.     public void process(List<String> results) {
  242.       for (String result : results)
  243.         textArea.append(result);
  244.     }
  245.  
  246.     // Called in the event thread when done() has terminated, whether
  247.     // by completing or by being cancelled.
  248.     public void done() {
  249.       try {
  250.         textArea.append(get());
  251.         textArea.append("Done");
  252.       } catch (InterruptedException exn) { }
  253.         catch (ExecutionException exn) { throw new RuntimeException(exn.getCause()); }
  254.         catch (CancellationException exn) { textArea.append("Cancelled"); }  // (3)
  255.     }
  256.   }
  257. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement