java — JLabel setForeground не работает в SwingWorker

#java #multithreading #swing #sleep

#java #многопоточность #swing #сон

Вопрос:

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

Подкласс SwingWorker:

 public class NewClass extends SwingWorker {
    private JLabel label;

    public NewClass(JLabel label) {
        this.label = label;
    }
    @Override
    protected Object doInBackground() throws Exception {
        while(true) {
            label.setForeground(Color.BLUE);
            try {
                sleep(1000);
            } catch (Exception ex) {
                 ex.printStackTrace();
            }

            label.setForeground(Color.RED);  
        }
    } 

    void changeColor() {
         Color c = label.getForeground();

         if(c == Color.RED)
            label.setForeground(Color.BLUE);
         else
            label.setForeground(Color.RED);
    }
}

public class NewJFrame extends javax.swing.JFrame {

    public NewJFrame() {
        initComponents();

        NewClass g = new NewClass(label);
        g.execute();


    }

    public static void main(String args[]) {

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NewJFrame().setVisible(true);
            }
        });
    }


    private javax.swing.JLabel label;

}
  

Но если я изменю doInBackground для использования моего метода changeColor, он будет работать хорошо:

 protected Object doInBackground() throws Exception {
        while(true) {
            changeColor();
            try {
                sleep(1000);
            } catch (Exception ex) {
                 ex.printStackTrace();
            }  
        }
}
  

Я не могу понять, почему это не выполняется в первом, я думал, что эти два способа одинаковы.

Комментарии:

1. Дополнительное примечание: вы обновляете графический интерфейс из фонового потока, а не EDT — потока отправки событий. Это не гарантировано для работы.

2. @JustanotherJavaprogrammer я думал, что с помощью SwingWorker можно обновить компонент Swing так же, как обновлять их в потоке EDT

3. Методы в Swingworker выполняются в разных потоках. Проверьте документацию о том, как это делается

Ответ №1:

Они не совпадают. В первом случае вы делаете следующее:

  • вы меняете цвет переднего плана на синий
  • вы ждете одну секунду
  • вы меняете цвет на красный
  • вы не ждете
  • вы меняете цвет на синий
  • вы ждете одну секунду
  • … ad infinitum