Results 1 to 9 of 9
- 01-20-2009, 08:39 PM #1
Member
- Join Date
- Jul 2008
- Posts
- 67
- Rep Power
- 0
SwingWorker and my small internet page downloader
I wrote this code to understand the processes of SwingWorker class which i have been trying to implement. I want to know is this right way to use SwingWorker or not ?
Java Code:import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.concurrent.ExecutionException; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; public class GetDataFromWeb extends JFrame { JTextArea downloadedDataArea; public GetDataFromWeb() { setTitle("Download data from internet!"); setSize(200, 250); JPanel northPanel = new JPanel(new FlowLayout()); final JTextField internetTextField = new JTextField(10); internetTextField.setText("http://www.google.com"); final JButton downloadButton = new JButton("Go!"); northPanel.add(internetTextField); northPanel.add(downloadButton); downloadedDataArea = new JTextArea(); JScrollPane downloadDataAreaScrollPane = new JScrollPane(downloadedDataArea); setLayout(new BorderLayout()); add(northPanel, BorderLayout.NORTH); add(downloadDataAreaScrollPane, BorderLayout.CENTER); downloadButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String address = internetTextField.getText(); if (address.length() > 0) { try { InternetDataTask task = new InternetDataTask(downloadedDataArea, address); task.execute(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }); setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new GetDataFromWeb(); } }); } } class InternetDataTask extends SwingWorker<String, Void> { URL url; InputStream in; JTextArea textArea; String address; public InternetDataTask(JTextArea area, String address) throws IOException { this.textArea = area; this.address = address; url = new URL(address); url.openConnection(); in = url.openStream(); } @Override protected String doInBackground() throws Exception { StringBuilder sb = new StringBuilder(); byte[] buffer = new byte[128]; while ((in.read(buffer)) != -1) { for (byte b : buffer) { // System.out.print((char)b); sb.append((char)b); } } in.close(); // textArea.append(sb + "\n"); return sb.toString(); } @Override protected void done() { try { textArea.append(get()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
-
Just on quick overview, it looks good. Question though: does it work as you'd expect it should?
- 01-20-2009, 10:19 PM #3
Member
- Join Date
- Jul 2008
- Posts
- 67
- Rep Power
- 0
Yes, but i am thinking about doInbackground method is implemented correctly? I am reading all the content into one string, is it right ?
-
As written, I see nothing wrong with your doInBackground method as you don't call any Swing code directly from it, which is good. Whether you wish to store the content in one String is a design issue that I think is distinct from whether or not the SwingWorker is written correctly.
Now if you want to show information in your app incrementally as the SwingWorker is doing its actions, then you should look into the process and publish methods.
- 01-20-2009, 10:59 PM #5
It looks good to me. The point of SwingWorker is that runs the logic on a background thread, but its done() method executes on the EDT, allowing you to update you Swing components.
What you do in doInBackground() is up to you. You can put the results in a String, or you could create an ArrayList and put each result as an entry in that. Bottom line, SwingWorker provides flexibility in how you return information.
You can also use the publish() and process() methods to handle results one at a time, so the display components will update incrementally. publish() operates in the worker thread, process() operates on the EDT.
Note that SwingWorker also allows you to add listeners for process events, and the listeners are also called on the EDT. The basic events are START and DONE; DONE is useful if you limit what the user can do while they are waiting. It also has other useful features.
- 01-22-2009, 04:40 PM #6
Member
- Join Date
- Jul 2008
- Posts
- 67
- Rep Power
- 0
Here is my next code i get it working but i dont get the exact that result which should be. Progressbar is not working correctly, like it's not receiving the progressbar state.
Also, this forum needs java highlighting!
Java Code:import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; public class SwingWorkerProgress extends JFrame { JTextArea downloadedDataArea; JProgressBar progressBar; public SwingWorkerProgress() { setTitle("Download data from internet!"); setSize(200, 250); downloadedDataArea = new JTextArea(); JScrollPane downloadDataAreaScrollPane = new JScrollPane(downloadedDataArea); progressBar = new JProgressBar(); progressBar.setMinimum(0); progressBar.setMaximum(100); JButton startButton = new JButton("Start"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { NumbersShow task = new NumbersShow(downloadedDataArea); task.addPropertyChangeListener( new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer)evt.getNewValue()); } } }); task.execute(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }); setLayout(new BorderLayout()); add(progressBar, BorderLayout.NORTH); add(downloadDataAreaScrollPane, BorderLayout.CENTER); add(startButton, BorderLayout.SOUTH); setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new SwingWorkerProgress(); } }); } } class NumbersShow extends SwingWorker<java.util.List<Integer>, Integer> { JTextArea textArea; int repeatTo = 100000; public NumbersShow(JTextArea area) throws IOException { this.textArea = area; } @Override protected java.util.List<Integer> doInBackground() throws Exception { int i = 0; java.util.List<Integer> numbers = new ArrayList<Integer>(); while (repeatTo > i && !isCancelled()) { publish(i); numbers.add(i); int progressAt = (int)(i / repeatTo * 100); // setProgress(progressAt); i++; } return numbers; } @Override protected void process(java.util.List<Integer> chunks) { for (int num : chunks) { textArea.append(num + "\n"); } } }
- 01-22-2009, 07:22 PM #7
setProgress causes a propertyChangeEvent to be fired. You must listen for these events, which include start and done as well.
- 02-08-2009, 09:14 PM #8
Member
- Join Date
- Jul 2008
- Posts
- 67
- Rep Power
- 0
Ok I actually gave up, but i am back again so i didn't understand your last post, so please give deeper explanation.
Do you mean by listening also start and done property or what ? In this block of code ?
Ok i made a more useful examplePHP Code:public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer)evt.getNewValue()); } }
Java Code:import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; public class SwingWorkerProgress extends JFrame { JTextArea downloadedDataArea; JProgressBar progressBar; public SwingWorkerProgress() { setTitle("Download data from internet!"); setSize(200, 250); downloadedDataArea = new JTextArea(); JScrollPane downloadDataAreaScrollPane = new JScrollPane(downloadedDataArea); progressBar = new JProgressBar(); progressBar.setMinimum(0); // progressBar.setMaximum(100); JButton startButton = new JButton("Start"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { NumbersShow task = new NumbersShow(downloadedDataArea); task.addPropertyChangeListener( new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer)evt.getNewValue()); } } }); task.execute(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }); setLayout(new BorderLayout()); add(progressBar, BorderLayout.NORTH); add(downloadDataAreaScrollPane, BorderLayout.CENTER); add(startButton, BorderLayout.SOUTH); setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new SwingWorkerProgress(); } }); } } class NumbersShow extends SwingWorker<String, String> { JTextArea textArea; final File path = new File("C:\\"); public NumbersShow(JTextArea area) throws IOException { this.textArea = area; } @Override protected String doInBackground() throws Exception { StringBuilder sb = new StringBuilder(); int size = path.list().length; int current = 0; for (String f : path.list()) { String temp = f; publish(temp); sb.append(temp); int progressAt = (int)(current / size * 100); setProgress(progressAt); current++; } return sb.toString(); } @Override protected void process(List<String> chunks) { for (String line : chunks) { textArea.append(line + "\n"); } } }
- 02-08-2009, 11:58 PM #9
You've made a lot of progress. I took your code and dumped it into Eclipse. I had to remove the code to retrieve data and replace it with a loop and a Thread.sleep() in doInBackGround(), but you app runs and updates the progress bar.
There is one significant issue! Do *not* use the process() method to do the data retrieval. Put that code back in doInBackground().
If you look carefully at the SwingWorker API, the publish() and process() methods work together. publish() allows the worker thread to store chunks of results, so the process() can retrieve the chunks and update the GUI *on the event dispatcher thread*. The goal is to allow the GUI to incrementally display data as it becomes available.
If that doesn't make sense, don't worry about it. It's an advanced capability, and you don't need to use it.
Good job on what you have so far. You also need to listen to "done" events, which indicate that the SwingWorker has completed its task. Often, you partially lock the GUI while work is done in background, perhaps only allowing the user a cancel option. When the task is done, the GUI is unlocked.
Similar Threads
-
SwingWorker Problem
By Berkan in forum Threads and SynchronizationReplies: 10Last Post: 03-11-2010, 03:28 AM -
SwingWorker problem!!! How can I run it 2 times or more?
By davigre in forum AWT / SwingReplies: 3Last Post: 10-02-2008, 05:48 AM -
Creating a Downloader using JAVA
By shinojkk in forum New To JavaReplies: 0Last Post: 01-08-2008, 05:08 PM -
Execute small java programs through Internet.........is thst possible??
By atanu.dey in forum New To JavaReplies: 1Last Post: 01-05-2008, 07:48 PM -
swingworker
By musiigedeo in forum AWT / SwingReplies: 1Last Post: 07-26-2007, 12:59 PM


LinkBack URL
About LinkBacks
Reply With Quote
Bookmarks