转自:http://tech.it168.com/jd/2008-07-04/200807040908028.shtml
我们在多文件下载或多事务处理时,经常会出现使用线程以提高效率的情况,而这时在GUI程序中如何表示进度,就成了一个不大不小的问题。
现在比较被大众接受的方式,大体就是如迅雷等下载工具中一样,用表格中加载进度条以进行显示。
而对于Swing来说,并没有现成的组件能够实现这一操作,还有下载的并发,似乎也需要额外进行处理。于是,我在此提供一个基于jdk1.6版 本的示例,以供参考。(因为jdk1.6提供了SwingWorker,简化了图形程序中的线程处理,使用其他jdk开发请替换此项即可)
本示例由两个java文件组成
MyTableModel.java
package org.loon.test; import java.awt.Component; import java.util.HashMap; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.JProgressBar; import javax.swing.JTable; import javax.swing.SwingWorker; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; /* * @author chenpeng * @email:[email protected] * @version 0.1 */ public class MyTableModel extends DefaultTableModel { /** *//** * */ private static final long serialVersionUID = 1L; private static final ColumnContext[] columnArray = { new ColumnContext("ID", Integer.class, false), new ColumnContext("名称", String.class, false), new ColumnContext("进度", Integer.class, false) }; private final Map< Integer, SwingWorker> swmap = new HashMap< Integer, SwingWorker>(); private int number = 0; public void addTest(Test t, SwingWorker worker) { Object[] obj = { new Integer(number), t.getName(), t.getProgress() }; super.addRow(obj); swmap.put(number, worker); number++; } public synchronized SwingWorker getSwingWorker(int identifier) { Integer key = (Integer) getValueAt(identifier, 0); return swmap.get(key); } public Test getTest(int identifier) { return new Test((String) getValueAt(identifier, 1), (Integer) getValueAt(identifier, 2)); } public boolean isCellEditable(int row, int col) { return columnArray[col].isEditable; } public Class< ?> getColumnClass(int modelIndex) { return columnArray[modelIndex].columnClass; } public int getColumnCount() { return columnArray.length; } public String getColumnName(int modelIndex) { return columnArray[modelIndex].columnName; } private static class ColumnContext { public final String columnName; public final Class columnClass; public final boolean isEditable; public ColumnContext(String columnName, Class columnClass, boolean isEditable) { this.columnName = columnName; this.columnClass = columnClass; this.isEditable = isEditable; } } } class Test { private String name; private Integer progress; public Test(String name, Integer progress) { this.name = name; this.progress = progress; } public void setName(String str) { name = str; } public void setProgress(Integer str) { progress = str; } public String getName() { return name; } public Integer getProgress() { return progress; } } class ProgressRenderer extends DefaultTableCellRenderer { /** *//** * */ private static final long serialVersionUID = 1L; private final JProgressBar b = new JProgressBar(0, 100); public ProgressRenderer() { super(); setOpaque(true); b.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Integer i = (Integer) value; String text = "完成"; if (i < 0) { //删除 text = "取消完毕"; } else if (i < 100) { b.setValue(i); return b; } super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column); return this; } }
MyPanel.java
package org.loon.test; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.util.HashSet; import java.util.Random; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTable; import javax.swing.RowFilter; import javax.swing.SwingWorker; import javax.swing.WindowConstants; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableRowSorter; / * * @author chenpeng * @email:[email protected] * @version 0.1 */ public class MyPanel extends JPanel { /** *//** * */ private static final long serialVersionUID = 1L; private static final Color evenColor = new Color(250, 250, 250); private final MyTableModel model = new MyTableModel(); private final TableRowSorter sorter = new TableRowSorter( model); private final JTable table; public MyPanel() { super(new BorderLayout()); table = new JTable(model) { /** *//** * */ private static final long serialVersionUID = 1L; public Component prepareRenderer( TableCellRenderer tableCellRenderer, int row, int column) { Component component = super.prepareRenderer(tableCellRenderer, row, column); //背景色及字体设置 if (isRowSelected(row)) { component.setForeground(getSelectionForeground()); component.setBackground(getSelectionBackground()); } else { component.setForeground(getForeground()); component.setBackground((row % 2 == 0) ? evenColor : table .getBackground()); } return component; } public JPopupMenu getComponentPopupMenu() { return makePopup(); } }; table.setRowSorter(sorter); model.addTest(new Test("进度条测试", 100), null); // 滚动条 JScrollPane scrollPane = new JScrollPane(table); // 背景色 scrollPane.getViewport().setBackground(Color.black); // 弹出菜单 table.setComponentPopupMenu(new JPopupMenu()); // 是否始终大到足以填充封闭视口的高度 table.setFillsViewportHeight(true); // 将单元格间距的高度和宽度设置为指定的Dimension table.setIntercellSpacing(new Dimension()); // 是否绘制单元格间的水平线 table.setShowHorizontalLines(true); // 是否绘制单元格间的垂直线 table.setShowVerticalLines(false); // 停止编辑时重新定义焦点,避免TableCellEditor丢失数据 table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); // 表示JTable中列的所有属性,如宽度、大小可调整性、最小和最大宽度等。 TableColumn column = table.getColumnModel().getColumn(0); column.setMaxWidth(60); column.setMinWidth(60); column.setResizable(false); column = table.getColumnModel().getColumn(2); // 绘制此列各值的TableCellRenderer column.setCellRenderer(new ProgressRenderer()); // 添加按钮 add(new JButton(new CreateNewAction("添加", null)), BorderLayout.SOUTH); add(scrollPane, BorderLayout.CENTER); setPreferredSize(new Dimension(320, 180)); } class CreateNewAction extends AbstractAction { /** *//** * */ private static final long serialVersionUID = 1L; public CreateNewAction(String label, Icon icon) { super(label, icon); } public void actionPerformed(ActionEvent evt) { createNewActionPerformed(evt); } } /** *//** * 创建事件 * @param evt */ private void createNewActionPerformed(ActionEvent evt) { final int key = model.getRowCount(); //在jdk1.6后,当一个Swing程序需要执行一个多线程任务时,可以通过javax.swing.SwingWorker实例进行实现。 //SwingWorker的process可以定义约束属性。更改这些属性将触发事件,并从事件调度线程上引起事件处理方法的调用。 //SwingWorker的done方法,在后台任务完成时自动的在事件调度线程上被调用。 SwingWorker< Integer, Integer> worker = new SwingWorker< Integer, Integer>() { // 随机sleep private int sleepDummy = new Random().nextInt(100) + 1; // 最大任务数量 private int taskSize = 200; protected Integer doInBackground() { int current = 0; while (current < taskSize && !isCancelled()) { current++; try { Thread.sleep(sleepDummy); } catch (InterruptedException ie) { publish(-1); break; } publish(100 * current / taskSize); } return sleepDummy * taskSize; } /** *//** * 进行中处理 */ protected void process(java.util.List data) { for (Integer value : data) { // 把数据填入对应的行列 model.setValueAt(value, key, 2); } // 传送变更事件给指定行列 model.fireTableCellUpdated(key, 2); } /** *//** * 完成后处理 */ protected void done() { } }; model.addTest(new Test("进度条测试", 0), worker); worker.execute(); } class CancelAction extends AbstractAction { /** *//** * */ private static final long serialVersionUID = 1L; public CancelAction(String label, Icon icon) { super(label, icon); } public void actionPerformed(ActionEvent evt) { cancelActionPerformed(evt); } } /** *//** * 取消进度 * @param evt */ public synchronized void cancelActionPerformed(ActionEvent evt) { int[] selection = table.getSelectedRows(); if (selection == null || selection.length <= 0) return; for (int i = 0; i < selection.length; i++) { int midx = table.convertRowIndexToModel(selection[i]); SwingWorker worker = model.getSwingWorker(midx); if (worker != null && !worker.isDone()) { worker.cancel(true); } worker = null; } table.repaint(); } /** *//** * 取消下载进程 * * @author chenpeng * */ class DeleteAction extends AbstractAction { /** *//** * */ private static final long serialVersionUID = 1L; public DeleteAction(String label, Icon icon) { super(label, icon); } public void actionPerformed(ActionEvent evt) { deleteActionPerformed(evt); } } private final HashSet set = new HashSet(); public synchronized void deleteActionPerformed(ActionEvent evt) { int[] selection = table.getSelectedRows(); if (selection == null || selection.length <= 0) return; for (int i = 0; i < selection.length; i++) { int midx = table.convertRowIndexToModel(selection[i]); set.add(midx); SwingWorker worker = model.getSwingWorker(midx); if (worker != null && !worker.isDone()) { worker.cancel(true); } worker = null; } // JTable过滤器 final RowFilter< MyTableModel, Integer> filter = new RowFilter< MyTableModel, Integer>() { public boolean include( Entry< ? extends MyTableModel, ? extends Integer> entry) { Integer midx = entry.getIdentifier(); return !set.contains(midx); } }; sorter.setRowFilter(filter); table.repaint(); } private JPopupMenu makePopup() { JPopupMenu pop = new JPopupMenu(); Action act = new CreateNewAction("添加", null); pop.add(act); act = new CancelAction("取消", null); int[] selection = table.getSelectedRows(); if (selection == null || selection.length <= 0) act.setEnabled(false); pop.add(act); // 分割线 pop.add(new JSeparator()); act = new DeleteAction("删除", null); if (selection == null || selection.length <= 0) act.setEnabled(false); pop.add(act); return pop; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { createGUI(); } }); } public static void createGUI() { JFrame frame = new JFrame("在JTable中加载进度条及进行操作"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.getContentPane().add(new MyPanel()); frame.setSize(400, 400); // 透明度90% // NativeLoader.getInstance().setTransparence(frame, 0.9f); // 居中 frame.setLocationRelativeTo(null); frame.setVisible(true); } }
转自:http://tech.it168.com/jd/2008-07-04/200807040908028.shtml