在swing中创建一个新线程是否安全?

时间:2017-11-21 20:12:18

标签: java multithreading swing

我创建了在performAction方法中执行某些操作的swing应用程序,但是当我创建一个显示progressBar的线程时,progressBar在performAction方法中将不可见,但最后,progressBar将以值100显示%直接
主要课程:

filename=$(scutil --get ComputerName); touch $filename.txt

窗口类:

    import javax.swing.*;
    import javax.swing.plaf.ButtonUI;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

public class main {
    public static void main(String[] args) {
        JFrame win = new JFrame("Test");
        FlowLayout layout = new FlowLayout();
        Button b1 = new Button("Click ");
        win.add(b1);
        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                window win = new window();
                win.start();
                try
                {
                    Thread.sleep(2000);
                }
                catch(InterruptedException e5){}
            }
        });
        win.setLayout(layout);
        win.setSize(500, 300);
        win.setLocationRelativeTo(null);
        win.setVisible(true);
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
}

1 个答案:

答案 0 :(得分:3)

是的,在Thread处理程序中创建新的actionPerformed是安全的。

但是,除了事件调度线程(EDT)之外,没有任何线程必须与Swing组件进行交互。

要在Swing中创建动画或延迟,您必须使用javax.swing.Timer。永远不允许在EDT上执行Thread.sleep(),并且不希望你希望这样做。

要从衍生线程返回EDT,您必须使用SwingUtilities.invokeLater()SwingUtilities.invokeAndWait()

使用SwingWorker是在Swing中执行后台任务的首选方法。它处理从后台任务到EDT的部分和最终结果的通信和发布,以便在GUI组件中显示。

以下是使用SwingWorker将代码翻译为工作示例。使用Swing Button代替AWT JButton。该程序使用invokeAndWait创建,以确保在EDT上进行主窗口构造。使用lambda函数,但如果需要,可以用new Runnable() { }内部类替换它。 “按钮0”到“按钮100”进度报告从SwingWorker后台任务发布,以便在EDT中进行处理。在EDT有机会处理它们之前,后台线程可以生成多个结果;在这里,我们只将最后一个结果显示在按钮中。

public class Main {

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeAndWait(() -> {
            JFrame win = new JFrame("Test");
            win.setLayout(new FlowLayout());
            JButton b1 = new JButton("Click");
            b1.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    DoWork work = new DoWork();
                    work.execute();
                }
            });
            win.add(b1);
            win.setSize(500, 300);
            win.setLocationRelativeTo(null);
            win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            win.setVisible(true);
        });
    }
}

class DoWork extends SwingWorker<Void, String> {
    JFrame fen;
    JButton b2;

    DoWork() {
        fen = new JFrame("New window");
        fen.setLayout(new FlowLayout());
        b2 = new JButton();
        fen.add(b2);
        fen.setSize(100, 100);
        fen.setLocationRelativeTo(null);
        fen.setVisible(true);
        fen.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    }

    @Override
    protected Void doInBackground() throws Exception {
        for (int i = 0; i <= 100; i++) {
            publish("Button " + i);
            Thread.sleep(10);
        }
        return null;
    }

    @Override
    protected void process(List<String> data) {
        String last = data.get(data.size() - 1);
        b2.setText(last);
    }

    @Override
    protected void done() {
        fen.dispose();
    }
}

可以对此代码进行一些改进。用于显示结果的JLabel代替JButton,进度窗口为JDialog,或者更好ProgressMonitor。这些留给了学生。