JTable的TableColumn添加多个JProgressBar

Posted

技术标签:

【中文标题】JTable的TableColumn添加多个JProgressBar【英文标题】:Adding multiple JProgressBar to TableColumn of JTable 【发布时间】:2011-10-25 13:09:51 【问题描述】:

我已将多个JProgressBar 添加到TableColumn 中的JTable

在进行某些计算后,我正在使用数据更新所有 JProgressBar,但只有添加的最后一个 ProgressBar(在本例中为 ProgressBar progressObj4)正在更新。

如何更新所有ProgressBars?

基本要求是我在上传时显示文件进度条的状态。目前我正在硬编码 4 个进度条来测试所有进度条是否都在更新文件的状态,但我需要动态创建它们。进度条的总数与正在上传的文件的数量有关。另外,如何获取进度条的各个实例并更新它们的状态?

我正在附上进度条的源代码被添加到表格列中。

//tc = object of TableColumn

progressObj1 = new ProgressBarRenderer("Progress1");
progressObj1.setValue(0);
progressObj1.setStringPainted(true);
progressObj1.setBackground(Color.WHITE);
progressObj1.setBorderPainted(true);

tc.setCellRenderer(progressObj1);

progressObj2 = new ProgressBarRenderer("Progress2");
progressObj2.setValue(0);
progressObj2.setStringPainted(true);
progressObj2.setBackground(Color.WHITE);
progressObj2.setBorderPainted(true);

tc.setCellRenderer(progressObj2);

progressObj3 = new ProgressBarRenderer("Progress3");
progressObj3.setValue(0);
progressObj3.setStringPainted(true);
progressObj3.setBackground(Color.WHITE);
progressObj3.setBorderPainted(true);

tc.setCellRenderer(progressObj3);

progressObj4 = new ProgressBarRenderer("Progress4");
progressObj4.setValue(0);
progressObj4.setStringPainted(true);
progressObj4.setBackground(Color.WHITE);
progressObj4.setBorderPainted(true);

tc.setCellRenderer(progressObj4);

【问题讨论】:

【参考方案1】:

据我所知,渲染器适用于给定列中的所有行。在我看来,您想将多个渲染器应用于同一列。此外,您似乎还试图赋予单元格渲染器状态。

我相信这将有助于使渲染器无状态,并让渲染器的方法 getTableCellRendererComponent() 在渲染器绘制单元格之前根据当前行的值设置各种 (JProgressBar) 属性。

换句话说,您应该只需要为任何给定列调用一次 tc.setCellRenderer(),然后让您的单元格渲染器为任何给定行绘制列(例如,基于该行的基础数据模型)表)。

【讨论】:

【参考方案2】:

基本上有两种方式移动JProgressBar,使用SwingWorker和Runnable#Thread,例如SwingWorker

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableCellProgressBar 

    private String[] columnNames = "String", "ProgressBar";
    private Object[][] data = "dummy", 100;
    private DefaultTableModel model = new DefaultTableModel(data, columnNames) 
        private static final long serialVersionUID = 1L;

        @Override
        public Class<?> getColumnClass(int column) 
            return getValueAt(0, column).getClass();
        

        @Override
        public boolean isCellEditable(int row, int col) 
            return false;
        
    ;
    private JTable table = new JTable(model);

    public JComponent makeUI() 
        TableColumn column = table.getColumnModel().getColumn(1);
        column.setCellRenderer(new ProgressRenderer());
        EventQueue.invokeLater(new Runnable() 

            @Override
            public void run() 
                startTask("test");
                startTask("error test");
                startTask("test");
            
        );
        JPanel p = new JPanel(new BorderLayout());
        p.add(new JScrollPane(table));
        return p;
    
//http://java-swing-tips.blogspot.com/2008/03/jprogressbar-in-jtable-cell.html

    private void startTask(String str) 
        final int key = model.getRowCount();
        SwingWorker<Integer, Integer> worker = new SwingWorker<Integer, Integer>() 

            private int sleepDummy = new Random().nextInt(100) + 1;
            private int lengthOfTask = 120;

            @Override
            protected Integer doInBackground() 
                int current = 0;
                while (current < lengthOfTask && !isCancelled()) 
                    if (!table.isDisplayable()) 
                        break;
                    
                    if (key == 2 && current > 60)  //Error Test
                        cancel(true);
                        publish(-1);
                        return -1;
                    
                    current++;
                    try 
                        Thread.sleep(sleepDummy);
                     catch (InterruptedException ie) 
                        break;
                    
                    publish(100 * current / lengthOfTask);
                
                return sleepDummy * lengthOfTask;
            

            @Override
            protected void process(java.util.List<Integer> c) 
                model.setValueAt(c.get(c.size() - 1), key, 1);
            

            @Override
            protected void done() 
                String text;
                int i = -1;
                if (isCancelled()) 
                    text = "Cancelled";
                 else 
                    try 
                        i = get();
                        text = (i >= 0) ? "Done" : "Disposed";
                     catch (Exception ignore) 
                        ignore.printStackTrace();
                        text = ignore.getMessage();
                    
                
                System.out.println(key + ":" + text + "(" + i + "ms)");
            
        ;
        model.addRow(new Object[]str, 0);
        worker.execute();
    

    public static void main(String[] args) 
        EventQueue.invokeLater(new Runnable() 

            @Override
            public void run() 
                createAndShowGUI();
            
        );
    

    public static void createAndShowGUI() 
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(new TableCellProgressBar().makeUI());
        frame.setSize(320, 240);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    


class ProgressRenderer extends DefaultTableCellRenderer 

    private final JProgressBar b = new JProgressBar(0, 100);

    public ProgressRenderer() 
        super();
        setOpaque(true);
        b.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
    

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) 
        Integer i = (Integer) value;
        String text = "Completed";
        if (i < 0) 
            text = "Error";
         else if (i < 100) 
            b.setValue(i);
            return b;
        
        super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column);
        return this;
    

【讨论】:

+1 用于错误测试!参照。这个相关的example。

以上是关于JTable的TableColumn添加多个JProgressBar的主要内容,如果未能解决你的问题,请参考以下文章

TableColumn setPreferredWidth不起作用

如何在JTable Invisible for Swing Java中创建一个列

向 Tableview Javafx 动态添加和删除 tablecolumn

Java Swing 如何使用DefaultTableModel交替刷新JTable?

Some JPR highlights (JPR 2019 March)

Java中具有相同ResultSet的多个jTable