Качайте компоненты, зависая, пока один компонент не завершит свою работу - PullRequest
4 голосов
/ 23 сентября 2011

Я создал простую программу JAVA Swing, которая имеет JTextArea, три JTextFields и один JButton. Это приложение выполняет, когда пользователь нажимает кнопку, с которой оно обновляет JTextArea текстовой строкой, текстовая строка, вставленная в JTextArea, подготавливается в цикле for, а количество повторений указывается в JTextField.

Моя проблема в том, что когда я нажимаю кнопку «Пуск», все компоненты приложения останавливаются, я даже не могу закрыть окно, пока цикл for не завершит свою работу. Как я могу отделить эту работу по обновлению JTextField от других задач в форме?

1 Ответ

9 голосов
/ 23 сентября 2011

Вы, вероятно, выполняете работу в потоке диспетчеризации событий (тот же поток, что и визуализация графического интерфейса).Используйте SwingWorker, вместо этого он будет выполнять работу в другом потоке.


Пример

Код ниже создает этот скриншот:

screenshot

Пример работника:

static class MyWorker extends SwingWorker<String, String> {

    private final JTextArea area;

    MyWorker(JTextArea area) {
        this.area = area;
    }

    @Override
    public String doInBackground() {
        for (int i = 0; i < 100; i++) {
            try { Thread.sleep(10); } catch (InterruptedException e) {}
            publish("Processing... " + i);
        }
        return "Done";
    }
    @Override
    protected void process(List<String> chunks) {
        for (String c : chunks) area.insert(c + "\n", 0);
    }
    @Override
    protected void done() {
        try {
            area.insert(get() + "\n", 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Пример main:

public static void main(String[] args) throws Exception {

    final JTextArea area = new JTextArea();

    JFrame frame = new JFrame("Test");

    frame.add(new JButton(new AbstractAction("Execute") {            
        @Override
        public void actionPerformed(ActionEvent e) {
            new MyWorker(area).execute();
        }
    }), BorderLayout.NORTH);

    frame.add(area, BorderLayout.CENTER);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.setVisible(true);
}
...