I think that one of the suffering things in UI is making a progress bar, you need to update it constantly while the operation is invoked by another thread and calculate the progress of the task.
From java 6.0 we have a new utility that help us with that called SwingWorker.
SwingWorker is an abstract class that you can extend and the abstract method called doInBackground that allow it to preform background operations. SwingWorker also can update the progress bar with the process method and by firing events for changes in the progress bar.
Let's see an example
In our example, we would like to send mails in the background for large number of users that defined in the Swing application. once the submit button is press the application will send the content of the mail to all the users, let's see the code of the application:
public class Application extends JFrame { // The UI Components private JProgressBar progressBar; private JTextArea mails; private JTextArea message; private JButton sendMails; private JLabel status; public Application(){ setSize(600, 600); message = new JTextArea(); JPanel rightPanel = new TextAreaPanel(new JLabel("message"), message); add(rightPanel, BorderLayout.EAST); mails = new JTextArea(); JPanel leftPanel = new TextAreaPanel(new JLabel("mails"), mails); sendMails = new JButton("send it!"); add(leftPanel, BorderLayout.WEST); add(sendMails, BorderLayout.NORTH); progressBar = new JProgressBar(); progressBar.setStringPainted(true); add(progressBar, BorderLayout.SOUTH); sendMails.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String addresses = mails.getText(); String[] add = addresses.split("\n"); SendMailsWorker worker = new SendMailsWorker(message.getText(), add); // A property listener used to update the progress bar PropertyChangeListener listener = new PropertyChangeListener(){ public void propertyChange(PropertyChangeEvent event) { if ("progress".equals(event.getPropertyName())) { progressBar.setValue( (Integer)event.getNewValue() ); } } }; worker.addPropertyChangeListener(listener); worker.execute(); } }); } // The main method public static void main(String[] args){ SwingUtilities.invokeLater(new Runnable(){ public void run(){ Application app = new Application(); app.setDefaultCloseOperation(EXIT_ON_CLOSE); app.pack(); app.setVisible(true); } }); System.out.println("finish main"); } } // and another class for handling the panel is public class TextAreaPanel extends JPanel{ public TextAreaPanel(JLabel label, JTextArea text) { text.setPreferredSize(new Dimension(120, 120)); add(label, BorderLayout.WEST); add(text, BorderLayout.CENTER); } }The action of sending the mail should be in the background, therefore, we should create a swing worker that handle the task, let's see it
public class SendMailsWorker extends SwingWorkeras you can see from the code, the operation of sending the mail is done by the SendMailWorker that extend SwingWorker. the method doInBackground preform the operation and set the progress so than you can write to the console or to any other place the progress of the writing. I think SwingWorker is very nice utility that simplify the ability to preform background operations.{ private final String message; private final String[] addresses; public SendMailsWorker(String mes, String[] mails) { message = mes; addresses = mails; } @Override protected Integer doInBackground() throws Exception { int matches = 0; for (int i = 0, size = addresses.length; i < size; i++) { // Update the status: the keep an eye on thing publish("send mail to: " + addresses[i]); matches += sendMail(message, addresses[i]); setProgress((i + 1) * 100 / size); } return matches; } private int sendMail(String message2, String string) { // sending the mail try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return 1; } @Override protected void process(List chunks) { for (String message : chunks) { System.out.println(message); } } @Override protected void done() { System.out.println("finish sending mails"); super.done(); } }
No comments:
Post a Comment