如果for循环在EDT内完成,则GUI卡住

时间:2015-09-25 08:40:18

标签: java multithreading user-interface

我有这段代码:

Thread T=new Thread(new Runnable(){
    public void run(){
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                for (int i=0;i<18;i++){
                    int percent=(int)(((i+1)*100)/18);
                    try {
                        lblNewLabel.setText("Loading... ("+percent+"%)");
                        Thread.sleep(1000);
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
});

我的问题是我的标签在这个线程被盯着之后不会改变它的文本,但是将保留旧文本(在此代码标签被创建为“Loading ...(0%)”文本之前)。 有没有办法避免这样做?

然后......如果我只在我的setText调用上调用invokeLater:

    SwingUtilities.invokeLater(new Runnable(){

        public void run(){

            lblNewLabel.setText("Loading...("+percent+"%)");
        }
    });

它将被调用18次。这是一个好方法吗?或者最好不要多次调用invokeLater方法?

谢谢

1 个答案:

答案 0 :(得分:1)

以下作品:

    public class UIThreadTest {

    private JFrame mainFrame;
    private JLabel labelStatus;
    private JButton buttonProcess;

    public static void main(String[] args) {
        final UIThreadTest ui = new UIThreadTest();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                ui.initGUI();
            }
        });
    }

    public void initGUI() {
        mainFrame = new JFrame("View");
        mainFrame.getContentPane().setLayout(new BorderLayout());
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.setSize(200, 200);
        mainFrame.setVisible(true);
        mainFrame.setLocationRelativeTo(null);

        labelStatus = new JLabel("Status...");
        mainFrame.getContentPane().add(labelStatus, BorderLayout.NORTH);

        buttonProcess = new JButton("Start");
        buttonProcess.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                Runnable startLoop = new StartLoop();
                Thread startLoopThread = new Thread(startLoop);
                startLoopThread.start();
            }

        });
        mainFrame.getContentPane().add(buttonProcess, BorderLayout.SOUTH);
    }

    private void updateStatus(final int val) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                labelStatus.setText("Loading... (" + val + "%)");
            }
        });

    }

    private void runForLoop() {
        for (int i = 0; i < 18; i++) {
            int percent = (int) (((i + 1) * 100) / 18);
            updateStatus(percent);
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private class StartLoop implements Runnable {
        @Override
        public void run() {
            runForLoop();
        }

    }
}