RandomDataDemo is an example of using SwingWorker to load data via JDBC in a background thread. More on concurrency in Swing may be found here and here.
import java.awt.BorderLayout;import java.awt.EventQueue;import java.awt.Font;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JProgressBar;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.SwingWorker;import org.h2.jdbcx.JdbcDataSource;/** * @author John B. Matthews */public class RandomDataDemo { private static final String RUN = "Run"; private static final String CANCEL = "Cancel"; private static final String QUIT = "Quit"; private static final JProgressBar progressBar = new JProgressBar(); private static final JTextArea textArea = new JTextArea(48, 120); private static final JButton run = new JButton(CANCEL); private static RandomDataTask task; public static void main(String[] args) throws Exception { EventQueue.invokeLater(new Runnable() { @Override public void run() { init(); } }); } private static void init() { JFrame frame = new JFrame("Random Data Demo"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); progressBar.setIndeterminate(true); frame.add(progressBar, BorderLayout.NORTH); textArea.setEditable(false); textArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); frame.add(new JScrollPane(textArea), BorderLayout.CENTER); JPanel panel = new JPanel(); run.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (RUN.equals(cmd)) { task.cancel(true); execTask(); run.setText(CANCEL); } else { task.cancel(true); run.setText(RUN); } } }); panel.add(run); JButton quit = new JButton(QUIT); quit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { task.cancel(true); System.exit(0); } }); panel.add(quit); frame.add(panel, BorderLayout.SOUTH); frame.pack(); frame.setVisible(true); execTask(); } private static void execTask() { textArea.replaceRange(null, 0, textArea.getSelectionEnd()); progressBar.setIndeterminate(false); task = new RandomDataTask(2500); task.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer) evt.getNewValue()); } } }); task.execute(); } /** * Get pseudo-random numbers from a data source. */ private static class RandomDataTask extends SwingWorker<List<Double>, Double> { private static final int BLOCK_SIZE = 10; private final int count; private final List<Double> numbers; private int index = 1; private Connection conn; private PreparedStatement ps; private ResultSet rs; RandomDataTask(int count) { this.count = count; this.numbers = new ArrayList<Double>(count); JdbcDataSource ds = new JdbcDataSource(); ds.setURL("jdbc:h2:file:~/src/java/jdbc/test;IFEXISTS=TRUE"); ds.setUser("sa"); ds.setPassword(""); try { this.conn = ds.getConnection(); ps = conn.prepareStatement( "SELECT RAND() FROM SYSTEM_RANGE(1, ?)"); ps.setInt(1, BLOCK_SIZE); } catch (SQLException ex) { ex.printStackTrace(System.err); } } @Override public List<Double> doInBackground() { try { for (int i = 0; i < count / BLOCK_SIZE; i++) { rs = ps.executeQuery(); while (rs.next() && !isCancelled()) { if (rs.getBoolean(1)) { double number = rs.getDouble(1); numbers.add(number); setProgress(100 * numbers.size() / count); publish(number); } } Thread.sleep(10); // simulate latency } } catch (SQLException ex) { ex.printStackTrace(System.err); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } return numbers; } @Override protected void process(List<Double> chunks) { StringBuilder strBuilder = new StringBuilder(); for (double number : chunks) { strBuilder.append(String.format("%1$11.8f", number)); if (index % BLOCK_SIZE == 0) { strBuilder.append('\n'); } index++; } textArea.append(strBuilder.toString()); } @Override protected void done() { run.setText(RUN); } }}Copyright © 2009 John B. Matthews. Distributed under the terms of the GPL