如何实施“进行中” Swing中的动画? [英] How to implement a "In Progress" animation in Swing?

查看:211
本文介绍了如何实施“进行中” Swing中的动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个执行一些长时间运行的函数的应用程序。为了让用户知道正在进行处理,我需要一个标签,可以显示一些可以代表该标签的标签。所以,我为这样的标签创建了一个小部件。

I am working on an application that executes some functions that run for long. To let the user aware that the processing is taking place, I needed a label that can display some label that can represent that. So, I created a small widget for such a label.

下面的程序运行find,我得到了我想要的输出。

The program below runs find and I get the output as I wanted.

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


/**
 * This is an extension to a JLabel that can be used to display an ongoing progress.
 * @author Ankit Gupta
 */
public class ProgressLabel extends JLabel {

    /**
     * The prefix label to which periods are added.
     */
    private String startLabel;
    /**
     * The label to display end of an operation.
     */
    private String endLabel;

    /**
     * Flag to indicate whether the animation is running or not.
     */
    private boolean running = false;
    //list to hold intermediate labels
    List<String> intermediateLabels;

    public ProgressLabel(String slbl, String elbl) {
        this.startLabel = slbl;
        this.endLabel = elbl;
        //initialize all the labels to be used once as creating them again and again is expensive
        intermediateLabels = new ArrayList<String>();
        intermediateLabels.add(startLabel+".");
        intermediateLabels.add(startLabel+"..");
        intermediateLabels.add(startLabel+"...");
        intermediateLabels.add(startLabel+"....");
    }

    public void done(){
        running = false;
    }

    public void start(){
        running = true;
        new LabelUpdateThread().start();
    }

    private class LabelUpdateThread extends Thread{
        int i;

        public LabelUpdateThread(){
            i=0;
        }

        @Override
        public void run(){
            while(running){
                SwingUtilities.invokeLater(new Runnable(){
                    @Override
                    public void run() {
                        setText(intermediateLabels.get((i++)%3));
                    }
                });

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {}
            }
            setText(endLabel);
        }
    }

    public static void main(String []args) throws InterruptedException{
        final JFrame frame = new JFrame("Testing ProgressLabel");
        JPanel panel = new JPanel();
        ProgressLabel progressLabel = new CZProgressLabel("Searching", "Done");
        panel.add(progressLabel);
        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(500,500));
        frame.pack();
        progressLabel.start();
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                frame.setVisible(true);
            } 
        });
        Thread.sleep(5000);
        progressLabel.done();
    }
}

然而,当我试图将其包含在应用程序中时,它没有按预期工作。我创建了一个带有按钮的小面板,并在 actionPerfomed()代码中使用了 ProgressLabel 的按钮像以前一样 start() done()方法,但这一次,标签只是在长度处理完成之前没有更新到 Done 。这是使用 ProgressLabel 的另一段代码,其中 actionPerformed()

However, when I tried to include this in the application, it did not work as expected. I created a small panel with a button and in the actionPerfomed() code for the button I used the ProgressLabel's start() and done() methods as before but this time, the label just did not update to Done until the length process finished. Here is another piece of code using the ProgressLabel with actionPerformed() :

public class SearchPanel extends JPanel {

    private JTextArea queryBox;
    private JButton searchBtn;
    private ProgressLabel progressLabel;
    private JSeparator queryAreaSeparator;

    public SearchPanel() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        //First Row
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.gridx = 0;
        queryBox = new JTextArea();
        queryBox.setRows(25);
        queryBox.setColumns(25);
        this.add(queryBox, gbc);


        //Second Row
        gbc.gridy = 1;

        gbc.gridwidth = 1;
        progressLabel = new ProgressLabel("Searching", "Done");
        this.add(progressLabel, gbc);

        gbc.gridx = 1;
        searchBtn = new JButton("Search");
        this.add(searchBtn, gbc);
        searchBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                progressLabel.start();
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException ex) {
                    Exceptions.printStackTrace(ex);
                }
                //the above sleep() call will be replace by some time-consuming process. It is there just for testing now

                progressLabel.done();
            }
        });


        gbc.gridx = 0;
    }

    /**
     * function to test CZSemanticSearchLabel
     */
    public static void main(String[] args) throws InterruptedException {
        final JFrame frame = new JFrame();
        CZSemanticSearchPanel panel = new CZSemanticSearchPanel();
        frame.add(panel);
        frame.setPreferredSize(new Dimension(500, 500));
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        Thread.sleep(10000);
        frame.dispose();


        final JFrame frame1 = new JFrame("Testing ProgressLabel");
        JPanel panel1 = new JPanel();
        CZProgressLabel progressLabel = new CZProgressLabel("Searching", "Done");
        panel1.add(progressLabel);
        frame1.add(panel1);
        frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame1.setPreferredSize(new Dimension(500, 500));
        frame1.pack();
        progressLabel.start();
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                frame1.setVisible(true);
            }
        });
        Thread.sleep(5000);
        progressLabel.done();
    }
}

我相信我已经搞砸了Swing的事件发送模型。但是,我无法想象什么?有人能告诉我这段代码有什么问题吗?我怎么纠正呢?

I believe that I have screwed something with Swing's Event dispatch model. But, I cannot figure what? Can someone tell me what is wrong with this code and how do I correct it?

推荐答案

我不知道你的实际情况代码,但你的示例代码有缺陷......

I don't know about your actual code, but your sample code is flawed...

在你的 ActionListener 中,你这样做......

In your ActionListener you are doing this...

progressLabel.start();
try {
    Thread.sleep(10000);
} catch (InterruptedException ex) {
    Exceptions.printStackTrace(ex);
}
//the above sleep() call will be replace by some time-consuming process. It is there just for testing now

progressLabel.done();

这将停止 事件调度线程,防止处理任何重绘请求(即没有屏幕更新)10秒钟。 。这也会让你的应用程序看起来像是挂起。

This will STOP the Event Dispatching Thread, preventing any repaint requests from the been handled (ie no screen updates) for 10 seconds...this will also make your application look like it's "hung".

我更新了你 ActionListener 这样读(注意我添加了一个 isRunning 方法,该方法从标签返回运行成员)

I updated you ActionListener to read like this (note I added a isRunning method which returns the running member from the label)

if (progressLabel.isRunning()) {
    progressLabel.done();
} else {
    progressLabel.start();
}

并且工作正常。

您可能希望阅读 Swing中的货币一些更多的想法。

You might like to read through Currency in Swing for some more ideas.

另外,正如已经建议的那样,SwingWorker可能是更好的方法

Also, as already suggested, SwingWorker may be a better approach

这篇关于如何实施“进行中” Swing中的动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆