Reputation: 93
Well, I have been working on a piece of code for almost 2 days now and not able to resolve the issue.
DESIRED BEHAVIOUR
The following code is supposed to display 10 strings one by one (the next replacing the previous one) with a gap of aprox. 200 ms.
q1 q2 q3 ...and so on upto q10
This display sequence starts when the user presses ENTER key.
REFLECTED BEHAVIOUR
The screen waits for aprox. 2 sec after pressing and then shows q10.
Some more info
stringText
changes value during execution (which I found by writing to console) but the same is not updated on screen (JFrame).displayQuestion(int number)
has a few unnecessary lines. I put them all because I was not sure what would work. Actually, nothing worked!THE CODE
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();
}
});
}
}
Upvotes: 2
Views: 697
Reputation: 17971
The timer is through a while loop - this may not be as per most people's liking, but lets forget it for the time being.
Actually we can't forget about this while loop because this is what is causing troubles. See, q120()
method is called when you click a button:
static class UserKeyCommand extends AbstractAction {
@Override // don't forget @Override annotation
public void actionPerformed( ActionEvent tf ) {
q120();
}
}
It means this code is executed in the context of the Event Dispatch Thread (EDT). This is a single and special thread where Swing components must be created/updated and event handling (i.e.: action events) must be performed. If we have a loop in this thread waiting for some condition to continue we'll block the EDT and GUI won't be able to repaint itself until the thread is unlocked.
For repetitive tasks (such as the one in your question) consider use a Swing Timer. For heavy tasks with interim results consider use a SwingWorker instead.
Upvotes: 4