Swing worker冻结了应用程序

时间:2017-01-18 13:58:40

标签: java swing

下面是一个小程序,它使用Newton-Raphson方法以高精度找出平方根。

除了SwingWorker之外,一切似乎都按预期工作。运行此应用程序时,应用程序将冻结,并且在SwingWorker完成其任务之前无法使用。但是,我认为SwingWorker的目的是避免这种情况。

有人可以帮我解决问题吗?

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DefaultCaret;

import net.miginfocom.swing.MigLayout;

@SuppressWarnings("serial")
public class SquareRoot extends JFrame {
    private BigDecimal SQRT_DIG = new BigDecimal(150);

    private SquareRoot() {
        super("Square Rooter");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        createLayout(this);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void createLayout(JFrame addTo) {
        JPanel rootPanel = new JPanel(new MigLayout("wrap", "grow", ""));
        JLabel acc = new JLabel("Accuracy: " + SQRT_DIG);
        JSlider accSlide = new JSlider(1, 1000000, 150);
        JLabel numRoot = new JLabel("Number to Square Root");
        JTextField num = new JTextField();
        JButton root = new JButton("Root");
        JLabel ansRoot = new JLabel("Answer");
        JTextArea ans = new JTextArea();
        JScrollPane ansHolder = new JScrollPane(ans);

        accSlide.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent arg0) {
                SQRT_DIG = new BigDecimal(accSlide.getValue());
                acc.setText("Accuracy: " + SQRT_DIG);
            }
        });
        rootPanel.add(acc);
        rootPanel.add(accSlide, "grow");

        root.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ans.setText("Please Wait");
                new SwingWorker<BigDecimal, Object>() {
                    @Override
                    protected BigDecimal doInBackground() throws Exception {
                        return bigSqrt(new BigDecimal(num.getText()));
                    }

                    @Override
                    protected void done() {
                        try {
                            ans.setText(get().toPlainString());
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                    }
                }.run();
            }
        });
        rootPanel.add(numRoot);
        rootPanel.add(num, "grow");
        rootPanel.add(root, "right");

        ans.setEditable(false);
        ((DefaultCaret) ans.getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
        ansHolder.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        rootPanel.add(ansRoot);
        rootPanel.add(ansHolder, "grow");

        addTo.add(rootPanel);
    }

    private BigDecimal sqrtNewtonRaphson(BigDecimal c, BigDecimal xn, BigDecimal precision) {
        BigDecimal fx = xn.pow(2).add(c.negate());
        BigDecimal fpx = xn.multiply(new BigDecimal(2));
        BigDecimal xn1 = fx.divide(fpx,2*SQRT_DIG.intValue(),RoundingMode.HALF_DOWN);
        xn1 = xn.add(xn1.negate());
        BigDecimal currentSquare = xn1.pow(2);
        BigDecimal currentPrecision = currentSquare.subtract(c);
        currentPrecision = currentPrecision.abs();
        if (currentPrecision.compareTo(precision) <= -1)
            return xn1;
        return sqrtNewtonRaphson(c, xn1, precision);
    }

    private BigDecimal bigSqrt(BigDecimal c) {
        return sqrtNewtonRaphson(c, new BigDecimal(1), new BigDecimal(1).divide(new BigDecimal(10).pow(SQRT_DIG.intValue())));
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new SquareRoot());
    }
}

1 个答案:

答案 0 :(得分:4)

我相信您的问题是由于您使用run()方法来执行SpringWorker。使用execute()代替将确保spring worker将在一个工作线程中运行。