Java: живое обновление прогресса загрузки в TextArea / JProgressBar с использованием JSch SFTP - PullRequest
2 голосов
/ 07 ноября 2011

У меня есть два файла классов upload.java и TransferProgress.java . upload.java создает графический интерфейс апплета и загружает файл на удаленный SSH-сервер. TransferProgress.java класс дает процент передачи. Процент загрузки завершен можно увидеть в консоли, но я хотел, чтобы он был виден на TextArea и на индикаторе выполнения Java. Поэтому я сделал TransferProgress.java , чтобы наследовать upload.java и добавить в TextArea .

Моя проблема в том, что TextArea и JProgressBar не обновляются во время передачи файла, но обновляются только после завершения передачи файла. После завершения передачи TextArea показывает журнал, а JProgressBar устанавливается на 100%. Мой код не обновляется TextArea и JProgressBar во время передачи файла.

Если я использую setText () вместо добавления для обновления TextArea, я вижу обновление прогресса в реальном времени, но ProgressBar все равно не обновляется в реальном времени.

Я не мог понять, где проблема. Я буду очень благодарен за вашу помощь.

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+" %");
        }
}

Ответы [ 3 ]

1 голос
/ 07 ноября 2011

Вам нужно обновить свой индикатор прогресса в отдельной теме.

Я бы предложил вашему Классу transferProgress (Примечание: имена классов должны начинаться с заглавной буквы) реализовать Runnable Interface , а затем использовать ExecutorService для запуска нового нить с этим классом.

1010 * Е.Г. *

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

}
0 голосов
/ 24 ноября 2011

Метод count () из класса TransferProgress дает процент выполнения 20 раз, пока файл не будет загружен.

В моем случае SwingUtilities.invokeLater не сработал.Я использовал SwingWorker, выполненный из класса загрузки, и он работал.(PS - я сделал прогрессбар в классе загрузки '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");

        }
}
0 голосов
/ 07 ноября 2011

Никогда не следует выполнять длительные действия из потока диспетчеризации событий (EDT), поскольку в это время графический интерфейс пользователя блокируется. Вы наблюдали здесь эффект этого. EDT - это поток, который запускает все прослушиватели действий, а также перерисовывает объекты GUI. Пока слушатель действия запущен, никакие другие события не будут отправлены, а также не будет происходить рисование => вы не увидите обновлений на индикаторе выполнения или в текстовой области. (Однако, они будут обновлены после того, как ваш слушатель действия завершит работу.)

Таким образом, используйте отдельный поток для загрузки файла, то есть все, что находится внутри else -блока в ActionListener, как в ответе flash.

Все, что обновляет GUI, должно быть снова выполнено в EDT, поэтому используйте EventQueue.invokeLater (или SwingUtilities.invokeLater) для части обновления GUI:

EventQueue.invokeLater(new Runnable() { public void run() {
       biforce.upload.progressBar.setValue(20);
       biforce.upload.txtArea.append(Integer.toString(this.percentage));
}});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...