обновление графического интерфейса из потока (другой класс)

У меня есть класс под названием Gui. Здесь я размещаю все свои ярлыки и кнопки. Он также содержит button.addactionlistener. При нажатии кнопки запускается другой поток (секундомер). Это когда секундомер входит в цикл, который продолжает обновлять ms,sec,min в цикле while.

Секундомер — это еще один файл класса. Секундомер содержит мс, сек, мин.

Как обновить метку графического интерфейса с секундомером мс, сек, мин?

public class Gui {

JFrame swFrame = new JFrame("Stopwatch");
Stopwatch sw = new Stopwatch();
Thread t1 = new Thread(sw);
private JPanel p;
private JButton b1;
private JButton b2;
private JButton b3;
private JLabel l1;
private JLabel l2;


public Gui()
{
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {

            swFrame.setSize(500,400);
            swFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            p = new JPanel();

            b1 = new JButton("StartStop");
            b2 = new JButton("LapTime");
            b3 = new JButton("Reset");

            l1 = new JLabel("bla");
            l2 = new JLabel("blala");

            p.add(b1);
            p.add(b2);
            p.add(b3);
            p.add(l1);
            p.add(l2);

            swFrame.add(p);
            b1.setActionCommand("StartStop");
            b2.setActionCommand("LapTime");
            b3.setActionCommand("Reset");
            b1.addActionListener(new ButtonClickListener());
            b2.addActionListener(new ButtonClickListener());
            b3.addActionListener(new ButtonClickListener());

        }
    });
}

private class ButtonClickListener implements ActionListener
{
      public void actionPerformed(ActionEvent e) 
      {
         String command = e.getActionCommand();  
         if( command.equals( "StartStop" ))
         {
            if(t1.isAlive())
            {
                t1.interrupt();
            }
            else
            {
                t1.start();
                !!!//How to update the jlabel from the moment t1.starts?!!!!
            }
         }
         else if( command.equals( "LapTime" ) )
         {
            l2.setText("Submit Button clicked."); 
         }
         else if(command.equals("Reset"))
         {

         }

      }     
   }

классный секундомер

public class Stopwatch implements Runnable 
{

private int min;
private int sec;
private long ms;
Timer timerSW = new Timer();
JLabel l1;


public void run()
{
    ms = System.currentTimeMillis();



    while(!Thread.currentThread().isInterrupted())
    {
        int seconds = (int) (ms / 1000) % 60 ;
        int minutes = (int) ((ms / (1000*60)) % 60);

    }
}

У меня также есть класс программы, который содержит основной метод. Это вызывает Gui.

public class Program {

public static void main(String[] args) 
{
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            Gui gui = new Gui();
            gui.swFrame.setVisible(true);
        }
    });

}

}


person Tuyen Phan    schedule 05.04.2016    source источник


Ответы (1)


Как обновить метку графического интерфейса с секундомером мс, сек, мин?

Осторожно, Swing не является потокобезопасным, и вы не должны изменять его состояние вне контекста потока диспетчеризации событий.

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

Более простым решением может быть использование Swing Timer вместо Thread, потому что Swing Timer выполняет свои уведомления в контексте EDT.

Рекомендуем ознакомиться с разделами Параллелизм в Swing и Как использовать таймеры Swing для более подробной информации

person MadProgrammer    schedule 05.04.2016
comment
Для этого упражнения мне нужно создать секундомер. Поток, который обновляет время. И с использованием компонентов качания Java. На данный момент я удалил SwingUtilities.invokeLater(new Runnable() в классе Gui. Что вы предлагаете мне делать? - person Tuyen Phan; 05.04.2016
comment
Положил его обратно. Я бы рекомендовал шаблон наблюдателя, поэтому каждый раз, когда ваш таймер обновляется, вы уведомляете наблюдателя, которому необходимо обновить пользовательский интерфейс. - person MadProgrammer; 05.04.2016