I have two class fils upload.java and transferProgress.java . upload.java makes applet GUI and uploads file to remote SSH server. transferProgress.java class gives transfer percentage. The upload percentage completed can be seen in console, but i wanted it to be seen on TextArea and on java progress bar. So i made transferProgress.java to inherit upload.java and append into TextArea .
My problem is, TextArea and JProgressBar do not get updated during the file transfer, but gets updated only when the file transfer is completed. After transfer completion, TextArea shows the log and JProgressBar get set to 100%. My code does not updates TextArea and JProgressBar during file transfer.
If i use setText() instead of append for updating TextArea, i can see real time progress update, but still ProgressBar do not get updated on real time.
I could not figure out where the problem is. I will be very thankful to your help.
upload.java
package biforce;
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class upload extends Applet
{
String filename;
int port = 22;
String user = "root";
String password = "mypass";
String host = "192.168.0.5";
String knownHostsFile = "/home/bishwo/.ssh/known_hosts";
String sourcePath = "";
String destPath = "/media/dfs/gwas/";
JTextField txtField = new JTextField(20);
static TextArea txtArea;
static JProgressBar progressBar;
@Override
public void init(){
// text Field
txtField.setEditable(false);
txtField.setText("");
// text area
txtArea = new TextArea(4,40);
txtArea.setEditable(false);
// JprogressBar
progressBar = new JProgressBar(0, 100);
progressBar.setValue(0);
progressBar.setStringPainted(true);
// Label
JLabel fileLabel = new JLabel("File");
// buttons
JButton upload = new JButton( "Upload" );
JButton browse = new JButton( "Browse" );
// browse file to be uploaded
browse.addActionListener(
new ActionListener()
{
@Override
public void actionPerformed( ActionEvent ae )
{
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory( new File( "/home/bishwo/Desktop/" ) );
int returnVal = fc.showOpenDialog( upload.this );
String filePath="";
if ( returnVal == JFileChooser.APPROVE_OPTION )
{
File aFile = fc.getSelectedFile();
filePath = aFile.getAbsolutePath();
filename = aFile.getName();
}
txtField.setText(filePath);
}
});
// upload the browsed file
upload.addActionListener(
new ActionListener()
{
@Override
public void actionPerformed( ActionEvent ae )
{
if(txtField.getText().length()==0)
{
JOptionPane.showMessageDialog(upload.this,"Please select a file to upload.","Error", JOptionPane.ERROR_MESSAGE);
}
else
{
try
{
sourcePath=txtField.getText();
JSch jsch = new JSch();
jsch.setKnownHosts(knownHostsFile);
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.connect();
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
txtArea.setText("Uploading..");
transferProgress progress = new transferProgress();
sftpChannel.put( sourcePath,destPath+filename, progress);
System.out.println("\nUpload Completed");
sftpChannel.exit();
session.disconnect();
JOptionPane.showMessageDialog(upload.this,"Upload completed successfully.","Info", JOptionPane.INFORMATION_MESSAGE);
}
catch(Exception e)
{
JOptionPane.showMessageDialog(upload.this,e,"Error", JOptionPane.ERROR_MESSAGE);
}
}
}
});
add(fileLabel);
add(txtField,"center");
add(browse);
add(upload);
add(progressBar);
add(txtArea);
}
}
transferProgress.java
import com.jcraft.jsch.*;
public class transferProgress extends upload implements SftpProgressMonitor
{
public double count=0;
private int percentage;
public double totalSize;
private int lastPercentage;
@Override
public void init(int op, String src, String dest, long max)
{
this.totalSize=max;
}
@Override
public boolean count(long count)
{
this.count += count;
this.percentage = (int) ((this.count / this.totalSize) * 100.0);
if (this.lastPercentage <= this.percentage - 5)
{
this.lastPercentage= this.percentage;
// setValue() does not work
biforce.upload.progressBar.setValue(20);
// append() does not work
biforce.upload.txtArea.append(Integer.toString(this.percentage));
// displays percentage completion on console
System.out.println("Upload Completion "+this.percentage+" %");
}
return true;
}
@Override
public void end()
{
System.out.println("Total Copied "+this.percentage+" %");
}
}
You need to update your progressbar in a seperate Thread.
I would suggest to let your Class transferProgress
(Note: Class names should start with a capital letter) implement the Runnable Interface and then use the ExecutorService to start a new thread with this Class.
Eg
public class TransferProgress extends upload implements SftpProgressMonitor, Runnable {
@Override
public void run() {
//update your progressbar here, basically the same as your count method
}
}
public class upload extends Applet {
//some code...
upload.addActionListener(
new ActionListener()
{
@Override
public void actionPerformed( ActionEvent ae )
{
//some code....
//start a new thread here which executes your run method in the TransferProgress class
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new TransferProgress());
//some code...
}
}
);
}
You should never do long-running actions from the event dispatch thread (EDT), since the GUI is blocked during this time. You observed here an effect of this. The EDT is the thread which runs all action listeners, and also repaints your GUI objects. As long as an action listener is running, no other events will be dispatched, and also no painting will occur => you will see no updates on your progress bar or text area. (They will be updated once your action listener finishes, though.)
Thus, use a separate thread to upload the file, ie everything inside the else
-block in the ActionListener, like in flash's answer.
Everything which updates the GUI then should be done in the EDT again, so use EventQueue.invokeLater
(or SwingUtilities.invokeLater
) for the GUI-updating part:
EventQueue.invokeLater(new Runnable() { public void run() {
biforce.upload.progressBar.setValue(20);
biforce.upload.txtArea.append(Integer.toString(this.percentage));
}});
count() method from transferProgress class gives progress percentage 20 times until the file gets uploaded.
In my case SwingUtilities.invokeLater did not work out. I used SwingWorker, executed from upload class and it worked. (PS - i made progressBar in the class upload 'public')
public class uploadWorker extends SwingWorker<Integer, Integer>
{
@Override
protected Integer doInBackground() throws Exception
{
//some codes .....
try{sftpChannel.put(upload.sourcePath,upload.destPath, new transferProgress()); }
catch(Exception e){System.out.println(e);}
Thread.sleep(1000);
return 42;
}
protected void done()
{
System.out.print("done");
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.