java - 如何在 Java 中正确实现自定义加载屏幕

标签 java swing loading splash-screen

我正在尝试用 Java 制作自定义加载屏幕(不使用 JProgressBar)。现在我刚刚尝试制作一个加载栏,用黑色矩形从左到右慢慢填充屏幕。为了测试这一点,我编写了一个简单的程序来分解随机数。我在单独的线程上运行因式分解代码,并且让图形每 100 毫秒获取一次因式分解的进度。但是,有时应用程序会在大约 10 秒内没有响应,然后继续运行。 如何在 Java 中正确实现自定义加载屏幕或者我现在使用的代码有什么问题?

这是代码:

public class Factorer implements Runnable, Loadable {

    private static Random r = new Random();

    private volatile int numOn;

    private volatile int numsTotal;

    public static void main(String[] args){

        Factorer fact = new Factorer(25);

        LoadingFrame f = new LoadingFrame(fact);
        fact.run();

    }

    public Factorer(int nNums){

        numsTotal = nNums;

    }

    public void factorRandomNumber(){

        int randomNumber = r.nextInt(Integer.MAX_VALUE);

        int n = randomNumber;

        List<Integer> factors = new ArrayList<Integer>();

        for (int i = 2; i <= n; i++) {

            while (n % i == 0) {

                factors.add(i);
                n /= i;

            }

        }

    }

    public void factorRandomNumbers(){

        for(numOn = 0; numOn < numsTotal; numOn++){

            factorRandomNumber();

        }

    }

    public float getProgress(){

        return ((float) numOn) / ((float) numsTotal);

    }

    @Override
    public void run() {

        factorRandomNumbers();

    }

}

这是可加载的界面:

public interface Loadable {

    public float getProgress();

}

这是图形类:

public class LoadingFrame extends JFrame {

    private static final long serialVersionUID = 8290713730328501888L;

    private static final int WIDTH = 400;
    private static final int HEIGHT = 400;

    private Loadable loadable;

    public LoadingFrame(Loadable l){

        super("Loading Test");

        this.loadable = l;

        this.setSize(WIDTH, HEIGHT);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        Timer t = new Timer(100, new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {

                repaint();

            }

        });

        t.start();

    }

    @Override
    public void paint(Graphics g){

        g.setColor(Color.BLACK);

        g.fillRect(0, 0, (int) (loadable.getProgress() * (float) WIDTH), HEIGHT);

    }

}

最佳答案

I run the factoring code on a separate thread

嗯,是的,也不是。您的 Factorer 类实现了 runnable,但您从不将该类视为单独的线程。

相反,您只需使用:

fact.run();

如果您尝试将此类用作可重用的单独线程,那么在代码中的某个位置您将拥有:

new Thread( new Factorer() ).start();

实际启动线程。

但是,由于 JVM 在与事件调度线程 (EDT) 不同的线程中启动,因此您的代码在单独的线程上运行,但这更多是出于偶然而不是设计。

此外,Factorer 类中的逻辑将不起作用,因为当您调用 getProgress() 方法时,您将始终获得相同的返回值。也就是说,factoroRandomNumbers() 数字在程序开始时执行一次,然后 numOnnumsTotal 将被初始化为其最终值.

public void paint(Graphics g){

你不应该重写paint()。自定义绘制是通过重写 JPanel 上的 paintComponent(...) 来完成的,然后将面板添加到框架中。

您的计时器逻辑不正确。您所做的就是调用 repaint(),但正如我之前所说,返回的值永远不会改变。您真正需要做的是调用像 getNextValue() 这样的方法。此方法将从包含随机数的 List 中获取一个值。

为了更好地理解 Swing 的工作原理,您需要阅读 Swing Tutorial 。您可能想从以下部分开始:

  1. Swing 中的并发
  2. 进行定制绘画

使用 SwingWorker 可能会更容易(如 Swing 中的并发部分所述)。这将为您创建一个单独的线程。然后你有循环代码生成一个随机值并“发布”这个值。发布此值后,您可以使用该值重新绘制框架。

关于java - 如何在 Java 中正确实现自定义加载屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42347658/

相关文章:

使用 ssh 和 ssl 的 java mongodb 连接

java - 下周在android上实现

java - JTextArea 按回车添加不必要的新行

java - 如何在 Java 中记录未捕获的异常?

jquery - HTML 加载动画

java - Sun JVM promise 虚拟内存高消耗

java - 使图像显示在 JButton 上

JAVA 将 Socket 包装为多屏 Swing 应用程序中的 Singleton 类

ASP.NET:当我的页面执行存储过程时,如何显示加载图像?

xml - Windows Phone 7 - 加载一个大的 xml 文件