问题
I have added multiple JProgressBar
to TableColumn
of JTable
.
I am updating all the JProgressBar with data after making certain calculations, but only the last ProgressBar
(in this case ProgressBar
progressObj4
) which is added is getting updated.
How can I update all the ProgressBar
s?
The basic requirement is that I am displaying the status of file in progress bar while uploading . Currently I am hardcoding 4 progress bars to test if all the progress bars are getting update wrt the status of the file, but I need to create them dynamically. The total no of progress bars wrt the no of files which is getting uploaded. Also, how can I fetch the individual instances of the progress bars & update their status ?
I am attaching the source code of the progressbar getting added to the table column.
//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:
basically there are two ways move with JProgressBar
by using SwingWorker and Runnable#Thread, example for 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;
}
}
回答2:
To my knowledge, a renderer applies to all rows in a given column. It seems to me that you would like to apply several renderers to the same column. Furthermore, it also seems that you are attempting to give the cell renderer state.
I believe it will help to make the renderer stateless and have the renderer's method getTableCellRendererComponent() take care of setting the various (JProgressBar) properties based on values from the current row before the renderer paints the cell.
In other words, you should only need to invoke tc.setCellRenderer() once for any given column, and then have your cell renderer to draw the column for any given row (based on, say, the underlying data model for that table).
来源:https://stackoverflow.com/questions/7036036/adding-multiple-jprogressbar-to-tablecolumn-of-jtable