2

I am writing a code in order to calculating the value of Pi, and sometimes could take a long time to calculate. I added a progress bar to show progress, but the code does exactly what I told it to, it opens the progress bar after the calculations and then immediately closes it (It closes when the value reaches 100.) I have attempted to stick the code for the progress bar into the loop, but soon I realized that solves the solution, but creates multiply progress bar windows. If placed before calculations, the progress bar remains at 0 (Obviously) I have displayed my code below:

import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.border.Border;
import java.util.Scanner;

public class PicCalc 
{
public static void main(String args[]) 
{
  Scanner keyboard = new Scanner(System.in);
  double i = 0;
    double stage = 1;
  int iterations = 1;
    int x = 3; //Simply a variable to calculate pi
  double y = -1.0; // Another variable for pi
    double myPi; //This is my calculation of Pi, don't eat it. 

  System.out.println("Hello! I calculate Pi and compare it to the acutal value of Pi!");
  System.out.println("How many iterations?");
  iterations = keyboard.nextInt();

  //Calculates Pi
  for (i = 1.0; i <= iterations; i++)
  {
         stage = stage + y/x;
         y = - y; //Flips Sign
         x+=2; 
  }

    myPi = 4*stage;
    System.out.println("My Pi: " + myPi);
    //STOP CALCULATING PI

    //CALCULATE PERCENT COMPLETE
  double percent = 100*(i/iterations);
  int intPercent = (int) (percent + 0.5); //Adds .5 in order to round.
  //STOP CALCULATING PERCENT COMPLETE

  //MAKES LOADING SCREEN
  JFrame f = new JFrame("Loading...");
  f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  Container content = f.getContentPane();
  JProgressBar progressBar = new JProgressBar();
  progressBar.setValue(intPercent);
  progressBar.setStringPainted(true);
  Border border = BorderFactory.createTitledBorder("Calcualating...");
  progressBar.setBorder(border);
  content.add(progressBar, BorderLayout.NORTH);
  f.setSize(300, 100);
  f.setVisible(true);
  //END OF MAKING LOADING SCREEN

 //CLOSES LOADING SCREEN WHEN 100% IS ACHIEVED
  if (percent >= 100)
  {
     f.dispose();
  }      
  //END OF CLOSING SCREEN HERE
Cdog101
  • 100
  • 1
  • 9

3 Answers3

5

You've only got one thread, so the GUI never gets a chance to update (because it's busy calculating).

The normal approach is to put the calculation in a background thread so the Event Dispatch Thread (EDT) [aka the GUI thread] is free to update the GUI.

See these for some guidance, and google will turn up plenty more.

How do you use the Event Dispatch Thread?

Java Background thread

Community
  • 1
  • 1
John3136
  • 28,809
  • 4
  • 51
  • 69
  • I am a first year java programmer, and I started to look into this stuff, but it flew over my head. I am sure this would be an excellent way to do this, and certainly more efficient than mine, but as of right now, FarmerJoe's answer made it simple. – Cdog101 Oct 25 '13 at 01:06
2

EDIT: I think if you take the changes in logic into account from my answer, and place it in a background process as John suggests, you'll be all set ;)

I think you may want to move your calculation of the percentage complete into your for loop so that it will update the progress as you make your iterations.

//MAKES LOADING SCREEN
JFrame f = new JFrame("Loading...");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = f.getContentPane();
JProgressBar progressBar = new JProgressBar();
progressBar.setStringPainted(true);
Border border = BorderFactory.createTitledBorder("Calcualating...");
progressBar.setBorder(border);
content.add(progressBar, BorderLayout.NORTH);
f.setSize(300, 100);
f.setVisible(true);

double percent = 0;
int intPercent = 0;
progressBar.setValue(intPercent);
//Calculates Pi
for (i = 1.0; i <= iterations; i++)
{
    stage = stage + y/x;
    y = - y; //Flips Sign
    x+=2; 
    //CALCULATE PERCENT COMPLETE
    percent = 100*(i/iterations);
    intPercent = (int) (percent + 0.5); //Adds .5 in order to round.
    progressBar.setValue(intPercent);
    //STOP CALCULATING PERCENT COMPLETE
}

myPi = 4*stage;
System.out.println("My Pi: " + myPi);
//STOP CALCULATING PI
Farmer Joe
  • 6,020
  • 1
  • 30
  • 40
  • @Cdog101: then you're doing something else wrong. farmerjoe is right, though, if you want to track the percent complete as it's happening, well, you've got to track it. The progress bar isn't going to magically know that it needs to be updated -- your code has to set its progress value. Threading is another issue that the good farmer hasn't discussed but which must be addressed. – Hovercraft Full Of Eels Oct 25 '13 at 00:57
  • Initially I thought he meant putting the entire jFrame stuffs into the loop, now I know what he means, and it works! Thanks, that solved my problem quickly and easily! – Cdog101 Oct 25 '13 at 01:04
0

you basically have 3 problems:

  1. percent calculation is out of for loop
  2. invalid percent calculation
  3. trying to display form after the calculation is done already

check full working code with my comments:

static private double myPi; // This is my calculation of Pi, don't eat it.
public static void main(String[] args)
{
    Scanner keyboard = new Scanner(System.in);

    System.out.println("Hello! I calculate Pi and compare it to the acutal value of Pi!");
    System.out.println("How many iterations?");
    final int iterations = keyboard.nextInt(); // me!!!: i needed to set 2000000000 to see actual window on my computer :)

    // MAKES LOADING SCREEN
    // me!!!: you should create frame before calculations, not after
    final JFrame f = new JFrame("Loading...");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    final Container content = f.getContentPane();
    final JProgressBar progressBar = new JProgressBar();
    progressBar.setStringPainted(true);
    Border border = BorderFactory.createTitledBorder("Calcualating...");
    progressBar.setBorder(border);
    content.add(progressBar, BorderLayout.NORTH);
    f.setSize(300, 100);
    f.setVisible(true);
    // END OF MAKING LOADING SCREEN

    // Calculates Pi
    Thread thread = new Thread() {
        public void run(){
            double stage = 1;
            int x = 3; // Simply a variable to calculate pi
            double y = -1.0; // Another variable for pi

            for (int i = 1; i <= iterations; i++)
            {
                stage = stage + y / x;
                y = -y; // Flips Sign
                x += 2;

                // CALCULATE PERCENT COMPLETE
                // me!!!: you're always getting 0 with your old method here
                double percent = 100.0 * i / iterations;
                int intPercent = (int) (percent + 0.5); // Adds .5 in order to round.
                progressBar.setValue(intPercent);
                // STOP CALCULATING PERCENT COMPLETE
            }
            myPi = 4 * stage;
        }
    };
    thread.start();
    try
    {
        thread.join();
    }
    catch (InterruptedException e)
    {
        e.printStackTrace();
    }

    System.out.println("My Pi: " + myPi);
    // STOP CALCULATING PI

    // CLOSES LOADING SCREEN WHEN 100% IS ACHIEVED
    f.dispose();
    // END OF CLOSING SCREEN HERE
}
Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57