在JTable中加载进度条及进行操作

简介:
我们在多文件下载或多事务处理时,经常会出现使用线程以提高效率的情况,而这时在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;

/** *//**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * @author chenpeng
 * @email:[email]ceponline@yahoo.com.cn[/email]
 * @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;

//import org.loon.framework.dll.NativeLoader;

/** *//**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * @author chenpeng
 * @email:[email]ceponline@yahoo.com.cn[/email]
 * @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<MyTableModel> sorter = new TableRowSorter<MyTableModel>(
            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<Integer> 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<Integer> set = new HashSet<Integer>();

    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);

    }
}

运行效果如下:



本文转自 cping 51CTO博客,原文链接:http://blog.51cto.com/cping1982/130108

相关文章
|
4月前
|
JavaScript
成功解决:el-dialog弹出窗口、数据第一次没有加载、第二次打开才能加载数据。(每次页面刷新后、第一次打开dialog窗口、图片数不加载)
这篇文章分享了解决Vue中`el-dialog`弹出窗口在第一次打开时数据未加载问题的技巧,通过改变组件的`key`属性来强制Vue重新渲染DOM,从而确保数据正确加载。
成功解决:el-dialog弹出窗口、数据第一次没有加载、第二次打开才能加载数据。(每次页面刷新后、第一次打开dialog窗口、图片数不加载)
刷新屏幕Cell 的一些方法
刷新屏幕Cell 的一些方法
65 0
datables之加载数据时显示进度条
datables之加载数据时显示进度条
93 0
|
前端开发
解决bootstrap table刷新加载时白色闪屏问题
解决bootstrap table刷新加载时白色闪屏问题
84 0
在Static控件上显示图片
在Static控件上显示图片
72 0
swing更改组件(删除后添加)得到心得:起码得刷新一下啊,可能还得再考虑重绘
swing更改组件(删除后添加)得到心得:起码得刷新一下啊,可能还得再考虑重绘
211 0
Dialog是逻辑字体,实际绘制时会选择不同字体
Dialog是逻辑字体,实际绘制时会选择不同字体
259 0