在设置JFrame的不透明度时,使用float和BigDecimal缺乏精度

时间:2014-07-27 23:42:36

标签: java swing fade precision bigdecimal

我希望标题有意义;我尝试使用SwingWorker创建淡入效果,以设置未修饰帧的不透明度。

我尝试将帧的不透明度设置为1.0以上时出现异常。当我打印出不透明度的每个增量时,结果如下:

0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001

我尝试使用BigDecimal,希望以某种方式保持精度,但它失败了。这是我的SwingWorker的代码:

private JFrame frame; //initialized in constructor of class

private SwingWorker<Void, Void> fadeIn = new SwingWorker<Void, Void>() {
    @Override
    protected Void doInBackground() throws Exception {
        BigDecimal decimal = new BigDecimal(".1");

        while(frame.getOpacity() < 1.0f)
            try {
                System.out.println(frame.getOpacity());
                frame.setOpacity(frame.getOpacity() + decimal.floatValue());
                Thread.sleep(30);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        return null;
    }

    public void done() {
        System.out.println("done");
    }
}; 

淡入效果很好,直到我得到这个异常(上面的代码没有捕获;必须手动捕获):

java.lang.IllegalArgumentException: The value of opacity should be in the range [0.0f .. 1.0f].
    at java.awt.Window.setOpacity(Window.java:3609)
    at java.awt.Frame.setOpacity(Frame.java:962)
    at gui.Splash$1.doInBackground(Splash.java:19)
    at gui.Splash$1.doInBackground(Splash.java:1)
    at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at javax.swing.SwingWorker.run(SwingWorker.java:334)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

有没有什么方法可以提高精确度?我知道我可以使用AlphaComposite并覆盖绘制方法,但我希望我能保持它现在的简单。

有什么方法可以让我更精确地确保我不会增加超出其允许范围的不透明度?

2 个答案:

答案 0 :(得分:1)

只需运行自己的值,忘记当前的不透明度:

protected Void doInBackground() throws Exception {

    for (int i = 1; i <= 10; i++)
        try {
            frame.setOpacity(i/10.0);
            Thread.sleep(30);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    return null;
}

这样您就可以保证最终到达1.0

答案 1 :(得分:0)

你可以简单地使用一个浮点数然后取浮点数的1.0和1.0以确保它在以下范围内:

frame.setOpacity(Math.Min(frame.getOpacity() + 0.1f, 1.0f));