My Jprogressbar is working strange, i have placed the jprogress in Jtable column, now the problem which i am facing is, if we dont touch progressbar, it work perfectly, but if we click on any row, all 3 progressbar will change there status to the progressbar which is presently running.
I am calling the following code
clsDownload(URLtoDownload,i,"file" + i ,JTable);
In clsDownload class, i am downloading file and also updating the progressbar, using
jTbl1.getModel().setValueAt(((int) dPercent)+"%", Loc, 1);
now from this code, if we click on any Jtable row, it will update the other progressbar also.
Here is the complete code having issue
public class ProgressCellRenderer extends JProgressBar
implements TableCellRenderer {
/**
* Creates a JProgressBar with the range 0,100.
*/
public ProgressCellRenderer(){
super(0, 100);
setValue(0);
setString("0%");
setStringPainted(true);
}
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
//value is a percentage e.g. 95%
final String sValue = value.toString();
int index = sValue.indexOf('%');
if (index != -1) {
int p = 0;
try{
p = Integer.parseInt(sValue.substring(0, index));
}
catch(NumberFormatException e){
}
setValue(p);
setString(sValue);
}
return this;
}
}
public class clsDownload implements Callable<String> {
private String fileURL;
private String localFileName;
private JTable jTbl1;
private int Loc;
clsDownload(String UrlName, int Jobpos, String lFileName, JTable tbl1)
{
try
{
fileURL = UrlName;
localFileName = lFileName;
jTbl1 = tbl1;
Loc= Jobpos;
}
catch (Exception e)
{
}
}
@Override
public String call() throws MalformedURLException, IOException
{
try
{
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
URL url = new URL(fileURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
BufferedOutputStream bout;
FileOutputStream fos;
Map<String,List<String>> hf = connection.getHeaderFields();
long ReceivedFlength =0;
double dPercent = 0;
//Check receiving file length
String searchKey = "Content-Length";
long downloaded =0; //initilze to 0 so that it dont take old value from above
in = new BufferedInputStream(connection.getInputStream());
fos=(downloaded==0)? new FileOutputStream(localFileName): new FileOutputStream(localFileName,true);
bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
int x = 0;
if(hf.containsKey(searchKey))
ReceivedFlength = Long.parseLong(hf.get(searchKey).get(0));
// progressBar = (JProgressBar)jTbl1.getComponent(8);
while ((x = in.read(data, 0, 1024)) >= 0 )
{
bout.write(data, 0, x);
downloaded += x;
//Display file download progress
dPercent = (downloaded*100)/ReceivedFlength;
if(dPercent > 1)
{
jTbl1.getModel().setValueAt(((int) dPercent)+"%", Loc, 1);
}
}
return "Completed";
}
catch(Exception e)
{
return "error";
}
}
}
private void btnLoadActionPerformed(java.awt.event.ActionEvent evt) {
tblFilestoDownload.setModel(new DownloadTable());
DownloadTable tblSelectedItem = (DownloadTable) tblFilestoDownload.getModel();
final TableColumn myCol = tblFilestoDownload.getColumnModel().getColumn(1);
myCol.setCellRenderer(new ProgressCellRenderer());
tblSelectedItem.insertData(new Object[]{"http://releases.ubuntu.com/14.04.1/ubuntu-14.04.1-server-amd64.iso",new JProgressBar(0,100)});
tblSelectedItem.insertData(new Object[]{"http://ports.ubuntu.com/ubuntu-ports/dists/precise-updates/main/installer-armhf/current/images/armadaxp/netboot/uImage",new JProgressBar(0,100)});
tblSelectedItem.insertData(new Object[]{"http://releases.ubuntu.com/14.04.1/ubuntu-14.04.1-server-amd64.iso",new JProgressBar(0,100)});
tblSelectedItem.insertData(new Object[]{"http://releases.ubuntu.com/14.04.1/ubuntu-14.04.1-server-amd64.iso",new JProgressBar(0,100)});
}
private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {
DoItWorker worker = new DoItWorker();
worker.execute();
}
class DoItWorker extends SwingWorker<Void, String>
{
public static final String INTERMEDIATE_RESULT = "intermediate result";
private static final long TIME_OUT = 5;
private final TimeUnit UNIT = TimeUnit.MINUTES;
private String intermediateResult;
private ExecutorService executor;
private CompletionService<String> completionService;
public DoItWorker() {
executor = Executors.newFixedThreadPool(1);
completionService = new ExecutorCompletionService<>(executor);
}
@Override
protected Void doInBackground() throws Exception {
for (int i = 0; i < tblFilestoDownload.getModel().getRowCount()-1; i++) {
Callable<String> callable = new clsDownload(tblFilestoDownload.getValueAt(0, i).toString(),i,"file" + i ,tblFilestoDownload);
completionService.submit(callable);
}
executor.shutdown();
for (int i = 0; i < tblFilestoDownload.getModel().getRowCount() -1 ; i++) {
String result = completionService.take().get();
publish(result);
int progress = (100 * i) / tblFilestoDownload.getModel().getRowCount();
setProgress(progress);
}
executor.awaitTermination(TIME_OUT, UNIT);
setProgress(100);
return null;
}
can you please help me, what i am doing wrong, why do all progressbar update when we click on any row of jtable.
Thanks
The problem is that TableCellRenderer is designed to reuse its (single) component getTableCellRendererComponent
for as many cells as possible, as optimisation on resources.
So the component should not be stateful, and at least set its full state in getTableCellRendererComponent
. (Hence all state provided: isSelected, hasFocus.)
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
// value is a percentage e.g. 95%
final String sValue = value.toString();
int p = 0;
int index = sValue.indexOf('%');
if (index != -1) {
try {
p = Integer.parseInt(sValue.substring(0, index));
}
catch(NumberFormatException e) {
}
}
// Always set full state:
setValue(p);
setString(sValue);
return this;
}