Как обновить JFrame Label в теме? - Джава - PullRequest
5 голосов
/ 23 ноября 2010

Я много пробовал, но не могу заставить его работать.

Мне сказали использовать EDT со следующим примером.

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            //  Modify the GUI here
        }
});

Я много читал на эту тему и до сих пор не понимаю. Я понимаю, что это за нить, но .invokeLater для меня все равно не имеет смысла. Честно говоря, если вы можете объяснить подробно это было бы большой помощью!

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

Ответы [ 5 ]

4 голосов
/ 23 ноября 2010

Итак, есть EDT (поток рассылки событий). Все действия, которые появляются на вашем экране, выполняются EDT. Существует только один EDT для приложения Swing.

Вы находитесь в какой-то произвольной теме и хотите обновить GUI через эту тему? Как я уже говорил, для каждого приложения Swing есть только один EDT, поэтому вы должны указать этому EDT для отображения метки (или любого другого контекста, который вы хотите).

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

2 голосов
/ 23 ноября 2010

Я рекомендую вам получить книгу Грязные богатые клиенты . Есть глава, в которой они объясняют модель потоков Swing очень подробно.

В основном в Swing любой код, который изменяет графический интерфейс, должен выполняться в потоке диспетчера событий. Используемый там класс SwingUtilities предоставляет вам простой способ отправлять события в очередь событий, которая затем отправляется EDT. Это то, что делает метод invokeLater, он принимает new Runnable() в качестве аргумента, который в конечном итоге выполняется в EDT.

Из книги:

Реализация invokeLater () принимает забота о создании и очереди специальных Событие, которое содержит Runnable. это событие обрабатывается на EDT в заказ был получен, как и любой другое событие. Когда приходит время, оно отправляется путем запуска Метод run () в Runnable.

0 голосов
/ 23 ноября 2010

Нужно быть членом, чтобы мы могли изменить его и при этом использовать его из внутреннего класса

protected long secret=0;

... это должно быть где-то в вашем коде, где оно будет запущено ...

JFrame f = new JFrame("foo");
new Thread(){
        public void run() {
            for(;;){
                try { 
                    sleep(1000);
                } catch Interrupted (Exception ix){ 
                    return;
                }
                // TODO update your secret key here
                // please don't use random()

                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        f.setTitle("secret "+x);
                    }
                });
            }
        }
   }).start();

....

Только обновляйте Swing из EDT, чтобы он правильно рисовал.

Когда вы находитесь в EDT (запускаете код в обработчике событий), вы можете вызывать paintImmediately (), если вам действительно нужно.

0 голосов
/ 23 ноября 2010

Это довольно распространенный элемент программирования GUI. У вас есть один поток, который обрабатывает отрисовку графического интерфейса, получение ввода и выполнение обратных вызовов. Если другой поток попытается изменить объекты, связанные с графическим интерфейсом, он будет конфликтовать с потоком графического интерфейса. Скажем, например, это было что-то наполовину через рисование чего-то, и вы меняете цвет из другого потока.

Все, что делает invokeLater, это ставит в очередь что-то для запуска потока GUI. К «позже» он действительно запускается практически мгновенно, но текущему потоку не нужно его ждать. Возможно, поток графического интерфейса выполняет отрисовку или ожидает возврата функции обратного вызова, что задержит выполнение кода, который вы ему дали.

0 голосов
/ 23 ноября 2010

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

private static final int WAIT_LENGTH = 1000; // 1 second
private JFrame frame = new JFrame();

// Thread will update the UI (via updateUI() call) about every 1 second
class UIUpdater extends Thread {
  @Override
  void run() {
    while (true) {
      try {
        // Update variables here
      }
      catch (Exception e) {
        System.out.println("Error: " + e);
      }
      finally {
        frame.repaint();
        Thread.sleep(WAIT_LENGTH);
      }
    }
  }
}

Для начала этой темы:

UIUpdater t = new UIUpdater();
t.start();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...