进度条:如何创建原始对象的深层副本

时间:2013-09-23 13:51:49

标签: java swing splash-screen runnable jwindow

我正在尝试在Java中使用类似于下面的进度条:

public class MyProgressSplashScreen extends JWindow
{
    private final JProgressBar progressbar;
    private final ExecutorService autoProgressExecutor = Executors.newFixedThreadPool(1);

    public MyProgressSplashScreen(final int theMin, final int theMax)
    {
        super();
        final JPanel contentPanel = new JPanel(new BorderLayout());
        contentPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
        if (theMin != -1 && theMax != -1)
        {
            progressbar = new JProgressBar(SwingConstants.HORIZONTAL, theMin, theMax);
        }
        else
        {
            progressbar = new JProgressBar(SwingConstants.HORIZONTAL);
            progressbar.setIndeterminate(true);
        }
        progressbar.setStringPainted(true);
        contentPanel.add(progressbar, BorderLayout.SOUTH);
        add(contentPanel);
        pack();
        setAlwaysOnTop(true);
    }

    public void showProgress(final int theValueTo, final int theEstimatedTimeInSeconds)
    {
        showProgress(progressbar.getValue(), theValueTo, theEstimatedTimeInSeconds);
    }

    public void showProgress(final int theValueFrom, final int theValueTo,
            final int theEstimatedTimeInSeconds)
    {
        setVisible(true);
        autoProgressExecutor.execute(new Runnable()
        {
            @Override
            public void run()
            {
                int numberOfSteps = theValueTo - theValueFrom;
                long timeToWait = TimeUnit.SECONDS.toMillis(theEstimatedTimeInSeconds)
                        / numberOfSteps;
                for (int i = theValueFrom; i <= theValueTo; i++)
                {
                    progressbar.setValue(i);
                    try
                    {
                        TimeUnit.MILLISECONDS.sleep(timeToWait);
                    }
                    catch (final InterruptedException e) {   }
                }
                if (progressbar.getValue() == 100) { setVisible(false);  }
            }
        });
    }
}

但是我无法传递MyProgressSplashScreen的副本,以便让单独的线程更新进度。 例如,下面的程序从0到10开始计数,然后从0到30重新启动,而它不应该重置为零!

public class TestSplashScreen
{
    private final MyProgressSplashScreen myProgressSplashScreen = new MyProgressSplashScreen(-1,-1);

    public static void main(String args[])
    {
        TestSplashScreen testInvoke = new TestSplashScreen();
        testInvoke.synchronize();
    }

    public void synchronize()
    {
        Runnable runnable = new Runnable()
        {
            @Override
            public void run()
            {
                myProgressSplashScreen.showProgress(10, 2);
                myProgressSplashScreen.toFront();

                MyRunnable myRunnable = new MyRunnable();
                myRunnable.setSyncProgressSplashScreen(myProgressSplashScreen);
                Thread t1 = new Thread(myRunnable);
                t1.start();
            }
        };
        runnable.run();
    }
}
class MyRunnable implements Runnable
{
    MyProgressSplashScreen syncProgressSplashScreen;
    public void setSyncProgressSplashScreen(MyProgressSplashScreen syncProgressSplashScreen)
    {
        this.syncProgressSplashScreen = syncProgressSplashScreen;
    }

    @Override
    public void run()
    {
        syncProgressSplashScreen.showProgress(30, 3);
    }
}

1 个答案:

答案 0 :(得分:1)

问题是您拨打syncProgressSplashScreen.showProgress 2次。它第一次阻塞线程使其从0增加到10然后再次从0到30调用它。删除读取myProgressSplashScreen.showProgress(10, 2);的行,它不会执行2次。另外我注意到你没有设置进度条的最大值,所以除非你打电话给myProgressSplashScreen.showProgress(100, 2),否则它不会达到100%。