[英]Swing worker freezes the application
下面是一个小程序,该程序利用牛顿-拉夫森方法以高精度找到平方根。
除了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());
}
}
我相信您的问题是由于您使用run()
方法执行SpringWorker而引起的。 相反,使用execute()
将确保spring worker在工作线程中运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.