2

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

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

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()中我像以前一样使用了start()done()方法,但是这一次,标签直到长度过程完成才更新为Done 。这是另一段使用with的代码:ProgressLabelProgressLabelactionPerformed()

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 的事件调度模型搞砸了。但是,我想不通是什么?有人能告诉我这段代码有什么问题吗?我该如何纠正?

4

2 回答 2

3

您可以使用SwingWorker:为此类事情制作的简单后台任务,而不是自己使用线程来实现这一点,并且链接的示例与您的问题非常相似。

start()不执行你的LabelUpdateThread().run(),但你的LabelUpdateThread().start()

于 2012-08-30T23:34:30.063 回答
3

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

在你的ActionListener你正在这样做......

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 秒......这也会使您的应用程序看起来像是“挂起”。

我更新了你ActionListener的阅读方式(注意我添加了一个从标签isRunning返回成员的方法)running

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

它工作正常。

您可能想通读Swing中的 Currency 以获得更多想法。

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

于 2012-08-30T23:46:03.497 回答