2013-03-01 3 views
0

У меня есть метод, который выполняется в EDT. Это что-то вроде этого:Проблемы с EDT-качанием

myMethod() 
{ 
    System.out.prinln(SwingUtilities.isEventDispatchThread()); 

    for (int i = 0; i < 10; i++) 
    { 
    Thread.sleep(3000); 
    someJPanel.remove(otherJPanel); 
    } 
} 

Что я ожидал, чтобы это произошло: Десять JPanels будут удалены из их родителей один за другим, с тремя вторыми паузами между каждым удалением ...

Что произошло на самом деле: Все замерло на 30 секунд, после чего все 10 элементов были удалены сразу.

Линия в консоли всегда была верна (SwingUtilities.isEventDispatchThread()).

Поскольку я делаю все это в EDT, почему изменения не мгновены? Почему он дожидается, когда метод достигнет своего конца?

Как мне изменить свой код для достижения трехсекундной задержки между абзацами?

+0

Вы удаляете компоненты, но фактическое удаление из пользовательского интерфейса делается немного позже –

+0

Я прекрасно знаю об этом. Как сделать это мгновенно? – Karlovsky120

+0

Вам нужно задерживать снаружи EDT. Ваш сон (3000) голодает от обычного пользовательского интерфейса Swing, включая фактическое удаление компонентов. См. Ответ MadProgrammer. –

ответ

7

Swing использует один поток для отправки событий и обработки запросов на перерисовку. Каждый раз, когда вы блокируете этот поток, вы останавливаете EDT от обработки этих запросов на перерисовку, чтобы пользовательский интерфейс выглядел так, будто он «остановлен».

Вместо этого используйте что-то вроде javax.swing.Timer, чтобы вставить задержку и выполнить действие. Это выполнит действие в EDT, но будет ждать в заднем потоке.

Есть прочитать The Event Dispatching Thread для деталей ...

Обновлен Таймер Пример

public class SlowDecline { 

    public static void main(String[] args) { 
     new SlowDecline(); 
    } 
    private TestPane last; 

    public SlowDecline() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       TestPane parent = new TestPane(Color.RED); 
       TestPane tp = add(parent, Color.BLUE); 
       tp = add(tp, Color.GREEN); 
       tp = add(tp, Color.CYAN); 
       tp = add(tp, Color.LIGHT_GRAY); 
       tp = add(tp, Color.MAGENTA); 
       tp = add(tp, Color.ORANGE); 
       tp = add(tp, Color.PINK); 

       last = tp; 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(parent); 
       frame.setSize(200, 200); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       Timer timer = new Timer(1000, new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         if (last != null) { 
          Container parent = last.getParent(); 
          if (parent != null) { 
           parent.remove(last); 
           parent.repaint(); 
           if (parent instanceof TestPane) { 
            last = (TestPane) parent; 
           } 
          } else { 
           last = null; 
          } 
         } else { 
          (((Timer)e.getSource())).stop(); 
         } 
        } 
       }); 
       timer.setRepeats(true); 
       timer.setCoalesce(true); 
       timer.start(); 
      } 
     }); 
    } 

    public TestPane add(TestPane parent, Color color) { 

     TestPane child = new TestPane(color); 
     parent.add(child); 
     return child; 
    } 

    public class TestPane extends JPanel { 

     public TestPane(Color background) { 
      setLayout(new BorderLayout()); 
      setBorder(new EmptyBorder(10, 10, 10, 10)); 
      setBackground(background); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(50, 50); 
     } 
    } 
} 
4

Это происходит потому, что поток пользовательского интерфейса отвечает за покраску экрана, а также обработок событий. Когда вы помещаете нить пользовательского интерфейса в режим ожидания, больше не происходит рисования или обработки событий. Когда поток возобновит рисование, все панели уже удалены.

Этот URL довольно популярен на how to handle threading with Swing.

Лучше всего создать нить, которая удаляет панели.

(непроверенный)

Thread t = new Thread() { 
    @Override 
    public void run() { // override the run() for the running behaviors 
    for (int i = 0; i < 10; i++) 
    { 
     Thread.sleep(3000); 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
      someJPanel.remove(...); 
      }); 
    } 
    } 
}; 
t.start(); // call back run() 
+0

Таким образом, фактическое удаление не выполняется из EDT, только визуальное? – Karlovsky120

+2

InvokeLater заставит панель удаляться по EDT. В приведенном выше примере кода избегается спать на EDT, поэтому вы не будете испытывать зависания пользовательского интерфейса. –

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