2014-12-18 2 views
1

В нашем проекте мой товарищ по команде замечает необычное поведение для радиокнопки, когда внутри прослушивателя действий присутствует вызов SwingUtilites.invokeLater. Archetecture прослушивателя действий не позволяет избежать этого вызова, потому что он предназначен для запуска другого потока, а затем возвращается обратно в AWT-поток.Радиоприемник не меняет состояние сразу

Есть ли способ исправить это? Я имею в виду изменение состояния отображаемого компонента.

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.ButtonGroup; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JRadioButton; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.WindowConstants; 

public class RadioButtonTest { 

public static void main(String[] args) { 
    try { 
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException 
      | UnsupportedLookAndFeelException e1) { 
     e1.printStackTrace(); 
    } 
    JFrame frame = new JFrame(); 
    JPanel panel = new JPanel(); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    frame.setSize(200, 200); 
    frame.add(panel); 
    ButtonGroup group = new ButtonGroup(); 
    JRadioButton b1 = new JRadioButton("Button 1"); 
    final JRadioButton b2 = new JRadioButton("Button 2"); 
    b2.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      Runnable action = new Runnable() { 

       @Override 
       public void run() { 
        try { 
         Thread.sleep(2500); 
        } catch (InterruptedException e) { 
         Thread.currentThread().interrupt(); 
         e.printStackTrace(); 
        } 
       } 
      }; 
      SwingUtilities.invokeLater(action); 
     } 
    }); 
    group.add(b1); 
    group.add(b2); 
    panel.add(b1); 
    panel.add(b2); 

    frame.setVisible(true); 
} 
} 

ответ

2

Использование SwingWorker, попробуйте этот код:

public void actionPerformed(ActionEvent arg0) { 
     SwingWorker<Object,Object> sw = new SwingWorker<Object,Object>() 
     { 
      @Override 
      protected Object doInBackground() throws Exception 
      { 
       try { 
        Thread.sleep(2500); 
       } catch (InterruptedException e) { 
        Thread.currentThread().interrupt(); 
        e.printStackTrace(); 
       } 
       return null; 
      } 
     }; 
     sw.execute(); 
} 

SwingWorker выполняется на отдельном рабочем потоке, который вызывается диспетчером потока событий путем вызова метода выполнения. Метод SwingUtilities.invokeLater просто накладывает метод запуска, который должен выполняться асинхронно в потоке диспетчеризации событий, поэтому вызов Thread.sleep внутри него заморозит поток отправки событий, который влияет на графический интерфейс.

4

Похоже, вы хотите избежать многократного запуска долгого задания фона. Вместо JRadioButton используйте родительский JToggleButton и установите его имя и действие в Отмените при запуске фоновой задачи. A Future, такой как SwingWorker, делает это удобным. Соответствующий пример с использованием JButton показан here.

Смежные вопросы