问题
I have created a scientific calculator program. What my program does is take "label" which is the string inputted by the user using buttons and evaluate the expression. What my program does is, as soon as the equal button (button_eq) is clicked, it calls the splitLabel method which splits the label into an Arraylist of numbers and operators. It then calls brackets which searches for brackets within the ArrayList and completes sub calculations by calling the method calculate. However, before when my program was handling more basic calculations (addition, subtraction) it was working fine. However, as soon as I added more complex calculations the program freezes when I click the equals button. I was wondering what the issue could be?
public class CalculatorFrameA {
ActionListener button_eqListener = new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
label2.setText(bracket(splitLabel(label.getText())));
}
};
public ArrayList<String> splitLabel(String val){
ArrayList<String> label_split = new ArrayList<String>();
String value = "";
String op = "";
for (int i = 0; i< val.length(); i++){
boolean isDigit = Character.toString(val.charAt(i)).matches("[0123456789.]+");
boolean isOperator = Character.toString(val.charAt(i)).matches("[+*/^-]+");
boolean isSin = (Character.toString(val.charAt(i)).equals("s") && Character.toString(val.charAt(i+1)).equals("i") && Character.toString(val.charAt(i+2)).equals("n"));
boolean isCos = (Character.toString(val.charAt(i)).equals("c") && Character.toString(val.charAt(i+1)).equals("o") && Character.toString(val.charAt(i+2)).equals("s"));
boolean isTan = (Character.toString(val.charAt(i)).equals("t") && Character.toString(val.charAt(i+1)).equals("a") && Character.toString(val.charAt(i+2)).equals("n"));
boolean isOpBracket = Character.toString(val.charAt(i)).equals("(");
boolean isClBracket = Character.toString(val.charAt(i)).equals(")");
while (isDigit){
value = value + Character.toString(val.charAt(i));
}
if (isOperator && !value.equals("")){
op = Character.toString(val.charAt(i));
label_split.add(value);
label_split.add(op);
op = "";
value = "";
} else if (isOperator && value.equals("")){
if (Character.toString(val.charAt(i)).equals("-")){
value = Character.toString(val.charAt(i));
}
} else if (isSin){
label_split.add("sin");
}else if (isCos){
label_split.add("cos");
}else if (isTan){
label_split.add("tan");
} else if (isOpBracket && !value.equals("")){
label_split.add(value);
label_split.add("(");
value = "";
} else if (isOpBracket && value.equals("")){
label_split.add("(");
} else if (isClBracket && !value.equals("")){
label_split.add(value);
label_split.add(")");
value = "";
}
if (i== val.length()-1 && !value.equals("")){
label_split.add(value);
} else if (i== val.length()-1 && Character.toString(val.charAt(i)).equals(")")){
label_split.add(")");
}
} return label_split;
}
public String bracket(ArrayList<String> label_split){
ArrayList<Integer> opBra = new ArrayList<Integer>();
ArrayList<Integer> clBra = new ArrayList<Integer>();
ArrayList<String> calculation = new ArrayList<String>();
int counter = 0;
int counter1 = 0;
if (label_split.contains("(") && label_split.contains(")")){
for (int j=0; j<label_split.size(); j++){
if (label_split.get(j).equals("(")){
counter = counter + 1;
opBra.add(j);
} else if (label_split.get(j).equals(")")){
counter1 = counter1 + 1;
clBra.add(j);
}
}
if (counter1 != counter){
return "error missing bracket";
} else {
for (int j=opBra.size(); j>0; j--){
int opBraPos = opBra.get(j) + 1; //+1 and -1 so it doesn't include ()
int clBraPos = clBra.get(opBra.size()-j) - 1;
opBra.remove(j);
clBra.remove(opBra.size()-j);
for(int t = 0; t < (clBraPos - opBraPos); t++){
calculation.add(label_split.get(t+opBraPos));
}
String value = calculate(calculation);
label_split.set(j , value);
calculation.clear();
for (int n = 0; n < ((clBraPos+1) - opBraPos); n++){
label_split.remove(n);
}
}
}
return calculate(label_split);
} else{
return calculate(label_split);
}
}
public String calculate(ArrayList<String> calculation){
double value = 0.0;
String value1 = "";
boolean isOperator = calculation.contains("[+*/^-]+");
boolean isSin = calculation.contains("sin");
boolean isCos = calculation.contains("cos");
boolean isTan = calculation.contains("tan");
boolean isOpBracket = calculation.contains("(");
boolean isClBracket = calculation.contains(")");
for (int i=0; i < calculation.size(); i++){
if (calculation.get(i).equals("^") && i < calculation.size() && i < 0){
boolean isDigit1 = calculation.get(i-1).matches("[0123456789.-]+");
boolean isDigit2 = calculation.get(i+1).matches("[0123456789.-]+");
if (isDigit1 && isDigit2){
value = Math.pow(Double.parseDouble(calculation.get(i-1)), Double.parseDouble(calculation.get(i+1)));
value1 = Double.toString(value);
calculation.set(i,value1);
calculation.remove(i-1);
calculation.remove(i+1);
}
}
}
for (int a=0; a < calculation.size(); a++){
if ( (calculation.get(a)).equals("sin") && a < calculation.size() && a < 0){
boolean isDigit1 = calculation.get(a+1).matches("[0123456789.-]+");
if (isDigit1){
value = Math.sin(Double.parseDouble(calculation.get(a+1)));
value1 = Double.toString(value);
calculation.set(a,value1);
calculation.remove(a+1);
}
}
}
for (int b=0; b < calculation.size(); b++){
if ( (calculation.get(b)).equals("cos") && b < calculation.size() && b < 0){
boolean isDigit1 = calculation.get(b+1).matches("[0123456789.-]+");
if (isDigit1){
value = Math.cos(Double.parseDouble(calculation.get(b+1)));
value1 = Double.toString(value);
calculation.set(b,value1);
calculation.remove(b+1);
}
}
}
for (int c=0; c < calculation.size(); c++){
if ( (calculation.get(c)).equals("tan") && c < calculation.size() && c < 0){
boolean isDigit1 = calculation.get(c+1).matches("[0123456789.-]+");
if (isDigit1){
value = Math.tan(Double.parseDouble(calculation.get(c+1)));
value1 = Double.toString(value);
calculation.set(c,value1);
calculation.remove(c+1);
}
}
}
for (int d=0; d < calculation.size(); d++){
if (calculation.get(d).equals("*") && d < calculation.size() && d < 0){
boolean isDigit1 = calculation.get(d-1).matches("[0123456789.-]+");
boolean isDigit2 = calculation.get(d+1).matches("[0123456789.-]+");
if (isDigit1 && isDigit2){
value = Double.parseDouble(calculation.get(d-1)) * Double.parseDouble(calculation.get(d+1));
value1 = Double.toString(value);
calculation.set(d,value1);
calculation.remove(d-1);
calculation.remove(d+1);
}
}
}
for (int e=0; e < calculation.size(); e++){
if (calculation.get(e).equals("/") && e < calculation.size() && e < 0){
boolean isDigit1 = calculation.get(e-1).matches("[0123456789.-]+");
boolean isDigit2 = calculation.get(e+1).matches("[0123456789.-]+");
if (isDigit1 && isDigit2){
value = Double.parseDouble(calculation.get(e-1)) / Double.parseDouble(calculation.get(e+1));
value1 = Double.toString(value);
calculation.set(e,value1);
calculation.remove(e-1);
calculation.remove(e+1);
}
}
}
for (int f=0; f < calculation.size(); f++){
if (calculation.get(f).equals("+") && f < calculation.size() && f < 0){
boolean isDigit1 = calculation.get(f-1).matches("[0123456789.-]+");
boolean isDigit2 = calculation.get(f+1).matches("[0123456789.-]+");
if (isDigit1 && isDigit2){
value = Double.parseDouble(calculation.get(f-1)) + Double.parseDouble(calculation.get(f+1));
value1 = Double.toString(value);
calculation.set(f,value1);
calculation.remove(f-1);
calculation.remove(f+1);
}
}
}
for (int g=0; g < calculation.size(); g++){
if (calculation.get(g).equals("-") && g < calculation.size() && g < 0){
boolean isDigit1 = calculation.get(g-1).matches("[0123456789.-]+");
boolean isDigit2 = calculation.get(g+1).matches("[0123456789.-]+");
if (isDigit1 && isDigit2){
value = Double.parseDouble(calculation.get(g-1)) - Double.parseDouble(calculation.get(g+1));
value1 = Double.toString(value);
calculation.set(g,value1);
calculation.remove(g-1);
calculation.remove(g+1);
}
}
}
for (int h=0; h < calculation.size(); h++){
boolean isDigit = calculation.get(h).matches("[0123456789.-]+");
if (isDigit && !isOperator && !isSin && !isCos && !isTan &&!isOpBracket &&!isClBracket){
double value3 = 0.0;
value3 = Double.parseDouble(calculation.get(h));
String value2 = Double.toString(value3);
calculation.set(h,value2);
}
}
return calculation.get(0);
}
public static void main(String[] args) {
CalculatorFrameA g = new CalculatorFrameA();
}
}
public static void main(String[] args) {
CalculatorFrameA g = new CalculatorFrameA();
}
回答1:
In stead of wrapping the call in a regular Thread
, make use of Swingutilities. You will need to do this since Swing isn't threadsafe. This way you will still be working on the EDT.
SwingUtilities.invokeLater(() -> {
try {
label2.setText(bracket(splitLabel(label.getText())));
} catch (Exception e) {
e.printStackTrace();
}
});
回答2:
The solution is to:
Use a separate
Thread
and useSwingUtilities.inovkeLater()
to place the text field updates on the EDT, orUse a
SwingWorker
, which has a built in API to support the above to features.
Read the section from the Swing tutorial on Concurrency in Swing for complete information and working examples of a SwingWorker.
回答3:
In the method where you call the calculations method, wrap the call in this:
public void actionPerformed(ActionEvent e){
Thread t = new Thread(new Runnable() {
public void run() {
try {
label2.setText(bracket(splitLabel(label.getText())));
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
}
this should solve the problem of the program freezing. if not pleasetell me
来源:https://stackoverflow.com/questions/40970045/java-swing-gui-freezes-when-completing-calculations-after-clicking-a-button