2014-11-08 2 views
2

Ну, я уже почти 2 дня работал над куском кода и не смог решить проблему.JLabel меняет значения через setText, но не обновляется на экране

желательное поведение

Следующий код должен отображать 10 строк по одному (следующая замена предыдущего) с зазором приблиз. 200 мс.

q1 q2 q3 ... и так далее ДО q10

Эта последовательность отображения начинается, когда пользователь нажимает клавишу ENTER.

ОТРАЖЕННАЯ ПОВЕДЕНИЕ

экран ждет приблиз. 2 секунды после нажатия, а затем показывает q10.

Некоторые подробнее

  1. Значение этикетки stringText изменения во время исполнения (который я нашел, написав на консоль), но так же не обновляется на экране (JFrame).
  2. Метка меняет значения через событие щелчка на кнопке, все остальное остается таким же (насколько это возможно).
  3. Таймер проходит через цикл while - это может быть не по нраву большинства людей, но в настоящее время забывает об этом.
  4. Метод displayQuestion(int number) имеет несколько ненужных линий. Я положил их все, потому что я не был уверен, что сработает. На самом деле ничего не получилось!

КОД

package sush4; 

import java.util.Date; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class Sush4 { 

    // Timer control variables 
    static long holdTimeWord = 200L; 
    static long elapsedTime = 0L; 

    // Counter for Strings displayed 
    static int i = 0; 

    // Strings in use 
    static String[] questionStack = {"q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10"}; 

    // UI: String display variables 
    static JLabel stringText; 
    static JFrame mainWindow; 

    // Key binding action object 
    private static Action userKeyCommand; 

    /// Display the question 
    private static void displayQuestion(int number) { 
     mainWindow.remove(stringText); 
     stringText.setText(questionStack[number]); 
     mainWindow.add(stringText); 
     mainWindow.setVisible(true); 
     mainWindow.revalidate(); 
     mainWindow.repaint(); 
    } 

    private static void q120(){ 

     //// Initiate the text 
     for(i = 0; i < questionStack.length; i++) { 

      displayQuestion(i); 

      //// And wait for Word hold time 
      long startTime = System.currentTimeMillis(); 
      elapsedTime = 0L; 
      // Now wait for event to happen 
      while ((elapsedTime < holdTimeWord)) { 
       elapsedTime = (new Date()).getTime() - startTime; 
      } 
     } 
    } 

    Sush4() { 

     //// Create the Window 
     mainWindow = new JFrame("Sush"); 
     mainWindow.setSize(700, 500); 
     mainWindow.setLayout(new FlowLayout()); 

     //// And add key bindings for user events 
     userKeyCommand = new UserKeyCommand(); 
     JRootPane rootPane = mainWindow.getRootPane(); 
     rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ENTER"), "doEnterAction"); 
     rootPane.getActionMap().put("doEnterAction", userKeyCommand); 

     // Terminate the program when the user closes the application. 
     mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     mainWindow.setResizable(false); 

     //// Add the text label 
     stringText = new JLabel("Random Text"); 
     mainWindow.add(stringText); 

     //// Finally, display the frame. 
     mainWindow.setVisible(true); 
    } 

    static class UserKeyCommand extends AbstractAction { 
     public void actionPerformed(ActionEvent tf) { 
      q120(); 
     } 
    } 

    public static void main(String[] args) { 

     // Create the frame on the event dispatching thread. 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       new Sush4(); 
      } 
     }); 
    } 
} 

ответ

3

Таймер через время цикла - это не может быть по душе большинства людей, но позволяет забыть на некоторое время.

На самом деле мы не можем забыть об этом во время цикла, потому что это то, что вызывает проблемы. См q120() метод вызывается при нажатии кнопки:

static class UserKeyCommand extends AbstractAction { 
    @Override // don't forget @Override annotation 
    public void actionPerformed(ActionEvent tf) { 
     q120(); 
    } 
} 

Это означает, что этот код выполняется в контексте Event Dispatch Thread (EDT). Это отдельный и специальный поток, в котором должны быть созданы/обновлены компоненты Swing и должны выполняться обработка событий (то есть: события действий). Если у нас есть цикл в этом потоке, ожидающий продолжения какого-либо условия, мы заблокируем EDT, и GUI не сможет перекрасить себя до тех пор, пока поток не будет разблокирован.

Для повторяющихся задач (например, в вашем вопросе) рассмотрите возможность использования Swing Timer. Для тяжелых задач с промежуточными результатами используйте вместо этого SwingWorker.

+0

Мое подозрение в том, что цикл OP только пытается моделировать/тестировать ожидаемое (в производстве: нециклическое) поведение. Таким образом, таймер или SwingWorker могут не понадобиться, если это так. – ryvantage

+0

@ryvantage, в то время как возможно маловероятно, что кто-то отправит код, который полностью отличается от тех, у кого проблемы. В любом случае использование Swing Timer - это способ сделать то, что указано в вопросе: * Следующий код должен отображать 10 строк один за другим (следующий, заменив предыдущий) пробелом aprox. 200 мс. * Если я что-то не хватает, конечно. – dic19

+0

Мой комментарий был в основном таким образом, что OP знает, что если его реальное приложение не использует цикл (и эту хакерскую систему задержки), то ему не понадобится таймер или качели, проблема, скорее всего, будет исправлена. Это не был копать или исправлять ваш ответ. – ryvantage

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