用于更新JLabel的多个线程

时间:2014-03-30 09:57:23

标签: java multithreading swing jlabel

以下代码是一个简单的JFrame,带有一个按钮和两个JLabels,代码的目标是通过调用一个新的Thread更新“JLabel,而不是试图在美国东部时间做到这一点。

我的问题是每次按下按钮时run方法都会调用一个新线程,但是它不会取消旧的线程。因此,如果您按下按钮,并在几秒钟后再次按下它,您将有两个线程更新JLabel,这看起来很糟糕。

问题声明:每次按下按钮,计数器必须从0开始,并且必须取消正在更新它的旧线程。

import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class MainFrame extends JFrame {

private JLabel countLabel1 = new JLabel("0");
private JLabel statusLabel = new JLabel("Task not completed.");
private JButton startButton = new JButton("Start");

public MainFrame(String title) {
    super(title);

    setLayout(new GridBagLayout());

    countLabel1.setFont(new Font("serif", Font.BOLD, 28));

    GridBagConstraints gc = new GridBagConstraints();

    gc.fill = GridBagConstraints.NONE;

    gc.gridx = 0;
    gc.gridy = 0;
    gc.weightx = 1;
    gc.weighty = 1;
    add(countLabel1, gc);

    gc.gridx = 0;
    gc.gridy = 1;
    gc.weightx = 1;
    gc.weighty = 1;
    add(statusLabel, gc);

    gc.gridx = 0;
    gc.gridy = 2;
    gc.weightx = 1;
    gc.weighty = 1;
    add(startButton, gc);

    startButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            start();
        }
    });

    setSize(200, 400);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
}


private void start() 
{
    Thread worker = new Thread() 
    {
        public void run() 
        {

            // Simulate doing something useful.
            for(int i=0; i<=10; i++) {

                final int count = i;

                SwingUtilities.invokeLater(new Runnable() 
                {
                    public void run() 
                    {
                        countLabel1.setText(Integer.toString(count));
                    }
                });

                try 
                {
                    Thread.sleep(1000);
                } catch (InterruptedException e) 
                {

                }
            }

            SwingUtilities.invokeLater(new Runnable() {
                public void run() 
                {
                    statusLabel.setText("Completed.");
                }
            });

        }
    };

    worker.start();
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            new MainFrame("SwingWorker Demo");
        }
    });
 }
   }

2 个答案:

答案 0 :(得分:3)

  

使用一些标志来停止前一个线程,就像它一样简单。

下次点击按钮时,您还没有更新statusLabel

试试这个

import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class MainFrame extends JFrame {

    private JLabel countLabel1 = new JLabel("0");
    private JLabel statusLabel = new JLabel("Task not completed.");
    private JButton startButton = new JButton("Start");

    private MyThread myThread;

    public MainFrame(String title) {
        super(title);

        setLayout(new GridBagLayout());

        countLabel1.setFont(new Font("serif", Font.BOLD, 28));

        GridBagConstraints gc = new GridBagConstraints();

        gc.fill = GridBagConstraints.NONE;

        gc.gridx = 0;
        gc.gridy = 0;
        gc.weightx = 1;
        gc.weighty = 1;
        add(countLabel1, gc);

        gc.gridx = 0;
        gc.gridy = 1;
        gc.weightx = 1;
        gc.weighty = 1;
        add(statusLabel, gc);

        gc.gridx = 0;
        gc.gridy = 2;
        gc.weightx = 1;
        gc.weighty = 1;
        add(startButton, gc);

        startButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                start();
            }
        });

        setSize(200, 400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    private void start() {
        if (myThread != null) {
            myThread.setRunning(false);
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                statusLabel.setText("Task not completed.");
            }
        });
        myThread = new MyThread(countLabel1, statusLabel);
        Thread thread = new Thread(myThread);
        thread.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MainFrame("SwingWorker Demo");
            }
        });
    }
}

class MyThread implements Runnable {

    public MyThread(JLabel countLabel1, JLabel statusLabel) {
        this.countLabel1 = countLabel1;
        this.statusLabel = statusLabel;
    }

    private boolean running = true;
    private JLabel countLabel1, statusLabel;

    public void run() {

        // Simulate doing something useful.
        for (int i = 0; i <= 10; i++) {

            if (running) {
                final int count = i;

                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        if (running) {
                            countLabel1.setText(Integer.toString(count));

                            if (count == 10) {
                                SwingUtilities.invokeLater(new Runnable() {
                                    public void run() {
                                        statusLabel.setText("Completed.");
                                    }
                                });
                            }
                        }
                    }
                });
            } else {
                break;
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
        }

    }

    public boolean isRunning() {
        return running;
    }

    public void setRunning(boolean running) {
        this.running = running;
    }

}

答案 1 :(得分:2)

检查此版本的代码。主要的新功能是实现Updater的{​​{1}}类。看看它是如何在这里使用的。另请参阅Runnable中的更改。另请参阅private void start()类中的enabled标志。

Updater