Java Swing - GUI freezes when completing calculations after clicking a button

时光毁灭记忆、已成空白 提交于 2020-11-29 10:16:27

问题


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:

  1. Use a separate Thread and use SwingUtilities.inovkeLater() to place the text field updates on the EDT, or

  2. Use 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!