问题
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
回答1:
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
回答2:
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
回答3:
you basically have 3 problems:
- percent calculation is out of for loop
- invalid percent calculation
- 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
}
来源:https://stackoverflow.com/questions/19579291/displaying-a-progress-bar-while-a-calculation-is-occuring