Swing: не удается заставить JButton обновить - repaint () не работает - PullRequest
7 голосов
/ 10 июня 2009

Я впервые использую Swing для создания простого графического интерфейса. Он состоит из JFrame, на который я поместил один JButton, который при нажатии вызывает другой код, который занимает прибл. 3 секунды, чтобы вернуться.

Непосредственно перед вызовом этого кода в actionPerformed() я хочу обновить текст на кнопке, чтобы информировать пользователя о том, что происходит обработка. Моя проблема в том, что текст на кнопке не обновляется до тех пор, пока не вернется 3-секундный вызов. Я хочу, чтобы обновленный текст присутствовал во время разговора, а затем я верну его обратно.

вызов repaint() на JButton ничего не делает, а вызов на JFrame приводит к выбрасыванию "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException", когда я нажимаю кнопку.

Ответы [ 2 ]

15 голосов
/ 10 июня 2009

То, что происходит, состоит в том, что 3-секундный код выполняется в потоке GUI, поэтому у кнопки нет шанса обновить, пока это не будет сделано.

Чтобы решить эту проблему, запустите SwingWorker для выполнения длительной операции; тогда вы по-прежнему можете делать что-то в графическом интерфейсе, пока вы ждете этого.

Вот пара из обучающих программ по предмету, и у SwingWorker Javadocs, упомянутых выше, также есть некоторый код.

Пример кода

public void actionPerformed(ActionEvent e) {
    SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
        @Override
        public Void doInBackground() {
            // Call complicated code here
            return null;
            // If you want to return something other than null, change
            // the generic type to something other than Void.
            // This method's return value will be available via get() once the
            // operation has completed.
        }

        @Override
        protected void done() {
            // get() would be available here if you want to use it
            myButton.setText("Done working");
        }
    };
    myButton.setText("Working...");
    worker.execute();
}
10 голосов
/ 10 июня 2009

Проблема здесь в том, что ваша долгосрочная задача блокирует поток, который обычно рисует графический интерфейс.

Обычный способ обойти это - выбросить более длинную задачу в другой поток.

Это можно сделать довольно легко, используя SwingWorker.

Этот вопрос может также предоставить некоторую полезную информацию.

...