1

I am sending a file over network using sockets. The file is received properly without any problem. But now I am using a JProgressBar to show percentage of file sent. My problem is that even when I update GUI in a separate thread, the progress bar is updated only when file is completely sent. I also tried adjusting the priority of main thread to Thread.MIN_PRIORITY but the problem still persisted.

The complete code is long so I am not posting it (I will post if someone asks). The short code for sending file and updating progress bar is

final double temp=(done/fileSize)*100; // percentage of file sent
SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        try
        {
            jpb.setString("Completed : "+temp+" %");
            jpb.setValue((int)temp); // this is executed only when 100%
        }      
        catch(Exception e) 
        {
            e.printStackTrace();
        }
    }
});
System.out.println(temp); // only this and
bos.write(b,0,read);      // this statement is executed
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Gagan93
  • 1,826
  • 2
  • 25
  • 38
  • 3
    Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling `Thread.sleep(n)` implement a Swing `Timer` for repeating tasks or a `SwingWorker` for long running tasks. See [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details. – Andrew Thompson Jan 11 '14 at 17:48
  • 1
    did you read official Oracle tutorial - How to use ProgressBar – mKorbel Jan 11 '14 at 17:49
  • 1
    `ProgressBar` If you mean `JProgressBar` please type that. If you don't please link to it. – Andrew Thompson Jan 11 '14 at 17:51
  • @andrew : sir, the above code is in a while loop which runs for quite long. I think that the bos.write(b,0,read) runs in the main thread, and GUI updation occurs in EDT. If this freezed my GUI, where should I update the progress bar – Gagan93 Jan 11 '14 at 17:52
  • @andrew : yup ..its JProgress bar, I am using Swing API – Gagan93 Jan 11 '14 at 17:52
  • 1
    In your code, after you have gone through the linked article. – Andrew Thompson Jan 11 '14 at 17:53
  • Yes, I have just read that article. Should I use SwingWorker to send that file, or to update GUI or both ? – Gagan93 Jan 11 '14 at 17:57
  • 1
    SwingWorker is intended to do time consuming tasks (database calls, download/upload files, huge processing stuff) in a background thread and update Swing components (such as JProgressBar) in the [Event Dispatch Thread](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html). So in this case is the way to go. See an example **[here](http://stackoverflow.com/questions/20498008/how-to-display-progress-bar-for-a-procedure-call/20498181#20498181)**. – dic19 Jan 11 '14 at 18:09

3 Answers3

0

Problem lies in below line:

final double temp=(done/fileSize)*100; // percentage of file sent

If done and fileSize are both not double then result of done/fileSize is 0.0.

Make them double (at least one of them) to keep the decimal part of the division.

Serdar
  • 383
  • 1
  • 9
  • both are double and I am printing the value of temp in CLI to debug. It is showing the correct value – Gagan93 Jan 11 '14 at 18:07
  • Can it be a starvation problem? As another GUI operations keep the swing event dispatcher thread busy. – Serdar Jan 11 '14 at 19:43
0

Here is a implementation that I talked about.

It's not the best design as I did it quick and dirty but this way the file transfer code is not dependent on the UI.

public class FileTransfer implements Runnable
{
    double transferPercent = 0.0;

    double getTransferPercent(){ return transferPercent; }

    @Override
    public void run()
    {
        while(transferingFile)
        {
            // Write data
            // Update transferPercent
        }
    }
}

public class UIClass extends TimerTask
{
    private FileTransfer fileTransfer;

    public void createUI()
    {
        TimerTask myClass = this;
        JButton b = new JButton("Transfer");
        b.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                fileTransfer.start();
                Timer t = new Timer();
                t.scheduleAtFixedRate(myClass, 0.0, 20);
            }
        });
    }

    // Update the UI here!
    @Override
    public void run()
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                jpb.setValue(fileTransfer.getTransferPercent());
            }
        });
    }
}
martyj
  • 14
  • 1
-1

I'd probably design this differently. I'd make the network code independent of the UI and have it just update a variable on percentage sent.

The UI would then poll this number with a timer to update the progress bar.

But your code should work. Try adding an @Override on your run function. Maybe SwingUltities.invokeLater is calling Runnable's run function instead of your own.

martyj
  • 14
  • 1
  • 2
    not this issue is called Event Dispatch Thread, Concurency in Swing, result is SwingWorker or Runnable#Thread with output to Swing GUI wrapped into invokeLater – mKorbel Jan 11 '14 at 17:48
  • elaborate a bit ...how would you design this ? – Gagan93 Jan 11 '14 at 17:48
  • My design would probably be something like this. – martyj Jan 11 '14 at 17:56
  • *"Maybe SwingUltities.invokeLater is calling Runnable's run function instead of your own."* Java has no functions. Classes have methods. Runnable is an interface so it has no *run* method implemented. – dic19 Jan 11 '14 at 18:17
  • A function is the same as a method. A method is a member function. – martyj Jan 11 '14 at 18:21
  • No it's not. Some programming languages treat these as synonyms but they are not. Function is a mathematical concept which implies a relation between a set of inputs and a set of outputs. Object Oriented Programming doesn't have concept of function but does have concept of method. Note a method not necessarily has to have an input and not necessarily has to have any output. Take a look to [Object-Oriented Programming Concepts](http://docs.oracle.com/javase/tutorial/java/concepts/object.html) – dic19 Jan 11 '14 at 18:40
  • So why does languages such as php and javascript use the keyword function? This isn't math. You can't compare a math definition to computer science. – martyj Jan 11 '14 at 18:52
  • Because PHP and javascript are not OO languages. PHP is a general purpose language and javascript is a scripting language. The keyword `function` is inherited from Procedural programming which is previous to Object Oriented paradigm. BTW Computer science was born thanks to mathematics, so plenty of concepts has been taken from there: function, set, variable, algorithm, array, matrix etc. – dic19 Jan 11 '14 at 19:09
  • php is OOP. Javascript is oop. You don't have to do OOP in java. You can have static functions. static void main(String[] args) – martyj Jan 11 '14 at 19:13