2013-03-23 1 views
1

Пожалуйста, посмотрите на следующий кодНевозможно обновить JDialog GUI внутри нити

private class EmergencyAlertNotifier implements Runnable, ActionListener 
    { 
     JDialog dialog = new JDialog(); 
     int number=0; 

     JLabel message; 
     JButton yes,no; 

     String messageStr; 

     public EmergencyAlertNotifier() 
     { 
      dialog.setLayout(new BorderLayout()); 

      //The JLabel which will display the number of seconds left 
      //before alerting emergency services 
      message = new JLabel(); 


      messageStr="number"; 

      yes = new JButton("OK"); 
      yes.addActionListener(this); 
      no = new JButton("Cancel"); 
      no.addActionListener(this); 

      JPanel btnPanel = new JPanel(); 
      btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); 
      btnPanel.add(yes); 
      btnPanel.add(no); 

      dialog.add(message,"Center"); 
      dialog.add(btnPanel,"South"); 

      dialog.setTitle("Ready To Notify Emergency Fire Services"); 
      dialog.setVisible(true); 
      dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     } 

     @Override 
     public void run() 
     { 
      for(int i=10;i>0;i--) 
      { 
       message.setText(messageStr+i+" Sec."); 


       try 
       { 
        Thread.sleep(1000); 
       } 
       catch(Exception e) 
       { 
        e.printStackTrace(); 
       } 
      } 


     } 

     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      if(e.getSource()==yes) 
      { 

      } 
      else 
      { 
       dialog.dispose(); 
      } 
     } 

    } 

Thread запускается вне указанного класса

new Thread(new EmergencyAlertNotifier()).start(); 

Я пытаюсь обновить JLabel с изменением числа внутри потока. Но вместо этого JLabel не подходит к графическому интерфейсу. Почему это? Пожалуйста помоги!

+2

Прежде всего, никогда, никогда не создавать, изменять или взаимодействовать с любым компонентом пользовательского интерфейса из любого другого потока События Диспетчерской Thread, проверить [Параллелизм в свинге] (http://docs.oracle.com/ javase/tutorial/uiswing/concurrency/index.html) для более подробной информации. Во-вторых, я не вижу там, где вы начинаете поток, так что вы уже выполняете его в контексте EDT, что означает, что вы его блокируете, не позволяя обновлять UI. – MadProgrammer

+0

@MadProgrammer: Спасибо за ответ. Пожалуйста, взгляните на редактирование –

+0

ОК, мне удалось решить проблему. Спасибо всем за ответы :) –

ответ

4
  • есть несколько вопросов в вашем коде, с Concurency in Swing,

  • пожалуйста, я не могу комментировать, что-то,

  • недо SwingWorker будет реализован в официальном API, Runnable#Thread был стандартным обходной путь для Workers Thread,

  • для производственного кода Runnable#Thread вместо SwingWorker (на мой взгляд, не согласны с черной дырой, реализованного в API)

  • выход из Runnable#Thread к Качели GUI требуется использование invokeLater, для thread_safe (setText, append ..., особенно там были chnages в Java7 в сравнении с Java6) методы слишком

  • использование util.Timer для count_down, вместо Thread.sleep()

модифицированный код, работает, как ожидалось

import java.awt.EventQueue; 
import java.awt.FlowLayout; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class EmergencyAlertNotifier implements Runnable, ActionListener { 

    private JDialog dialog = new JDialog(); 
    private int number = 0; 
    private JLabel message; 
    private JButton yes, no; 
    private String messageStr; 
    private boolean runProcess = true; 

    public EmergencyAlertNotifier() { 
     dialog.setLayout(new GridLayout()); 
     //The JLabel which will display the number of seconds left 
     //before alerting emergency services 
     message = new JLabel(); 
     messageStr = "number"; 
     yes = new JButton("OK"); 
     yes.addActionListener(this); 
     no = new JButton("Cancel"); 
     no.addActionListener(this); 
     JPanel btnPanel = new JPanel(); 
     btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); 
     btnPanel.add(yes); 
     btnPanel.add(no); 
     dialog.add(message, "Center"); 
     dialog.add(btnPanel, "South"); 
     dialog.setTitle("Ready To Notify Emergency Fire Services"); 
     dialog.pack(); 
     dialog.setVisible(true); 
     dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     new Thread(this).start(); 
    } 

    @Override 
    public void run() { 
     while (runProcess) { 
      for (int i = 10; i > 0; i--) { 
       message.setText(messageStr + " " + i + " Sec."); 
       try { 
        Thread.sleep(1000); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
      runProcess = false; 
     } 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     if (e.getSource() == yes) { 
     } else { 
      dialog.dispose(); 
     } 
    } 

    public static void main(String args[]) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       EmergencyAlertNotifier ean = new EmergencyAlertNotifier(); 
      } 
     }); 
    } 
} 
+1

Альтернатива, использующая 'javax.swing.Timer', показана [здесь] (http://stackoverflow.com/a/12451673/230513). – trashgod

+0

Спасибо за ответ :). Я думаю, вы правы. Моя нить не закрывается даже графическим интерфейсом! ahhhhhhhhhhh! Я двигаюсь с таймером –

+0

Спасибо за совет mKorbel :) –