In the code below I am running my method which adds text to a JTextArea, then i wait 4 seconds and add more text. However it simply waits four seconds then puts all the text down at once. How can I make it so it adds the first text, waits then adds the second block of text?
public static void configuresettings() {
GUI.add("To Begin, Go to www.opionsxo.com");
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
GUI.add("Welcome to Configure Settings!");
}
I figured it out, if anyone is interested in how. Then view the code below...
public static void configuresettings() {
GUI.add("To Begin, Go to www.opionsxo.com");
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
GUI.add("Welcome to Configure Settings!");
}
};
Timer timer = new Timer( 4000, actionListener );
timer.setRepeats(false);
timer.start();
}
You shouldn't use Thread.sleep with swing, or it will block your application. For instance, if you resize your window or move a window in front of your application, it won't repaint as needed, because you stopped it. Instead, you should be using Swing Timers.
Your problem is probably because you should revalidate() your JTextArea before sleep or something, but as said, you should change the implementation of it.
Read more here: http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
Don't do anything within the context of the Event Dispatching Thread that might cause it to stop, like calling Thread.sleep.
Instead, trying using a javax.swing.Timer or SwingWorker
Take a look at:
Concurrency in Swing
Worker Threads and SwingWorker
How to Use Swing Timers
For more details
For example:
java for-loop in GUI TextArea
Displaying contents of String array in Swing component as iterations using Time delay. JAVA
I cant run JTextArea multiple times?
Related
this is how I'm trying to accomplish this:
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello there");
Thread.sleep(1000);
panel.updateUI();
}
});
I set Enter button as the default button so when I keep pressing it the button press maybe 100 times or more but because I'm using Thread.sleep(1000) it takes some time so I have time to type in my JtextField or even close the window but can't do anything.
also, I tried to put btnNewButton.addActionListener() in the run method of a thread but no difference.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello there");
Thread.sleep(1000);
panel.updateUI();
}
});
}
});
thread.start();
// I used try catch block in real code
can anyone help me to solve the issue?
**I'm creating this application in eclipse using windowsBuilder.
This is because of something that is called EDT - the Event Dispatch Thread.
This special purpose thread is responsible for all the events in your GUI - including drawing (refreshing) and interactions (button click). This means, that exactly the same thread is used to draw your application as the one that is used to execute actionPerformed code. Since you are literally halting that thread for some amount of time, your application will be non responsive for that exact period of time.
Whatever is being executed on user interactions should be short and execute fast for the reason of not blocking the application. If you need to do some heavy stuff, there is a facility for that purpose called SwingWorker that allows you to easily do some processing in the background thread (pool) and schedule UI updates during execution (like update of progress bar)
In your second "thread" snippet, your thread is not doing anything beside adding actionListener to the button, and then it terminates (probably after less than 1ms ;)) - action callback is still executed by the EDT. If you would start that custom thread from inside of run method - then it would be indeed in parallel and GUI would not be frozen - but again, SwingWorker is the way to go here.
Not entirely sure what your code is supposed to do, but if you want to press the button and then 1000ms later it will check your field you should do something like this:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("before 1000ms");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("after 1000ms");
System.out.println("Reading the text field ...");
}
});
thread.start();
System.out.println("after the thread");
Output:
after the thread
before 1000ms
after 1000ms
Reading the text field ...
I have an array of strings which I'm trying to display (one by one) as a slideshow in a Java Swing component. I am also trying to add a delay time between the iterations.
I attempted to do this by using a JTextArea, with an action listener added to it. Here is the code I have right now:
private class myActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// A BUNCH OF TEXT PROCESSING
//NOTE: myInfo.getContents() returns an ArrayList<myType>.
Iterator<myType> iterator = myInfo.getContents().iterator();
int i = 0;
while (iterator.hasNext()) {
myTextArea.setText(iterator.next().toString());
// to add time betweeen iterations i wanted to use the thread
// delay method.
}
}
}
My code is not working because JTextArea doesn't have an action listener.
UPDATE
NOTE: Many replies stated that I should use an ActionListener for the JTextArea; However, Eclipse is not showing me that JTextArea has a method called addActionListener.
I'm kind of stuck here, which Java Swing component do you think would be the most suitable in this scenario?
The text in my array may be long, so a one lined label would not be a good choice.
What other alternatives or approaches do I have?
Thank you very much, any help and suggestions are appreciated.
This is basic example is based on the suggestion posted by #Robin
public class TestDisplayString {
public static void main(String[] args) {
new TestDisplayString();
}
public TestDisplayString() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextArea textArea;
private List<String> content;
private Iterator<String> iterator;
public TestPane() {
readText();
setLayout(new BorderLayout());
textArea = new JTextArea(10, 40);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
add(new JScrollPane(textArea));
iterator = content.iterator();
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (iterator.hasNext()) {
textArea.setText(iterator.next());
} else {
((Timer)e.getSource()).stop();
}
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
protected void readText() {
content = new ArrayList<>(25);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/Text.txt")));
String text = null;
while ((text = reader.readLine()) != null) {
if (text.trim().length() > 0) {
content.add(text);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
}
}
This is the contents of the "Text.txt" file.
How to Use Swing Timers
A Swing timer (an instance of javax.swing.Timer) fires one or more
action events after a specified delay. Don't confuse Swing timers with
the general-purpose timer facility that was added to the java.util
package in release 1.3. This page describes only Swing timers.
In general, we recommend using Swing timers rather than
general-purpose timers for GUI-related tasks because Swing timers all
share the same, pre-existing timer thread and the GUI-related task
automatically executes on the event-dispatch thread. However, you
might use a general-purpose timer if you don't plan on touching the
GUI from the timer, or need to perform lengthy processing.
You can use Swing timers in two ways:
To perform a task once, after a delay.
For example, the tool tip manager uses Swing timers to determine when to show a tool tip and when to hide it.
To perform a task repeatedly.
For example, you might perform animation or update a component that displays progress toward a goal.
Swing timers are very easy to use. When you create the timer, you
specify an action listener to be notified when the timer "goes off".
The actionPerformed method in this listener should contain the code
for whatever task you need to be performed. When you create the timer,
you also specify the number of milliseconds between timer firings. If
you want the timer to go off only once, you can invoke
setRepeats(false) on the timer. To start the timer, call its start
method. To suspend it, call stop.
Note that the Swing timer's task is performed in the event dispatch
thread. This means that the task can safely manipulate components, but
it also means that the task should execute quickly. If the task might
take a while to execute, then consider using a SwingWorker instead of
or in addition to the timer. See Concurrency in Swing for instructions
about using the SwingWorker class and information on using Swing
components in multi-threaded programs.
Let's look at an example of using a timer to periodically update a
component. The TumbleItem applet uses a timer to update its display at
regular intervals. (To see this applet running, go to How to Make
Applets. This applet begins by creating and starting a timer:
timer = new Timer(speed, this); timer.setInitialDelay(pause);
timer.start();
The speed and pause variables represent applet parameters; as
configured on the other page, these are 100 and 1900 respectively, so
that the first timer event will occur in approximately 1.9 seconds,
and recur every 0.1 seconds. By specifying this as the second argument
to the Timer constructor, TumbleItem specifies that it is the action
listener for timer events.
After starting the timer, TumbleItem begins loading a series of images
in a background thread. Meanwhile, the timer events begin to occur,
causing the actionPerformed method to execute:
public void actionPerformed(ActionEvent e) {
//If still loading, can't animate.
if (!worker.isDone()) {
return;
}
loopslot++;
if (loopslot >= nimgs) {
loopslot = 0;
off += offset;
if (off < 0) {
off = width - maxWidth;
} else if (off + maxWidth > width) {
off = 0;
}
}
animator.repaint();
if (loopslot == nimgs - 1) {
timer.restart();
} }
Until the images are loaded, worker.isDone returns false, so timer
events are effectively ignored. The first part of the event handling
code simply sets values that are employed in the animation control's
paintComponent method: loopslot (the index of the next graphic in the
animation) and off (the horizontal offset of the next graphic).
Eventually, loopslot will reach the end of the image array and start
over. When this happens, the code at the end of actionPerformed
restarts the timer. Doing this causes a short delay before the
animation sequence begins again.
Use your ActionListener in combination with a javax.Swing.Timer. The ActionListener assigned to the Timer will be called on regular intervals with the specified delay.
See the timer tutorial for more information
How can I smoothly move the JButton if action performed (eg the button is pushed). Here's my example but it doesnt work propely:
public void actionPerformed(ActionEvent event) {
for(int i = 0; i<50; i++){
ww.button.setLocation(ww.button.getLocation().x+1, ww.button.getLocation().y);//ww is a JFrame child
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
After action performed I get a delay in 20*50 ms and button location set in previous loc + 50px, without intermediate locations.
Always try to avoid Thread while working with Swing. In your code it will make main EDT thread to sleep and that's why you are not able to view intermediate locations. Try this with using Swing Timer and you will get it working as intended. Take a look here: How to Use Swing Timers and also try using Swing workers.
I have an array of strings which I'm trying to display (one by one) as a slideshow in a Java Swing component. I am also trying to add a delay time between the iterations.
I attempted to do this by using a JTextArea, with an action listener added to it. Here is the code I have right now:
private class myActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
// A BUNCH OF TEXT PROCESSING
//NOTE: myInfo.getContents() returns an ArrayList<myType>.
Iterator<myType> iterator = myInfo.getContents().iterator();
int i = 0;
while (iterator.hasNext()) {
myTextArea.setText(iterator.next().toString());
// to add time betweeen iterations i wanted to use the thread
// delay method.
}
}
}
My code is not working because JTextArea doesn't have an action listener.
UPDATE
NOTE: Many replies stated that I should use an ActionListener for the JTextArea; However, Eclipse is not showing me that JTextArea has a method called addActionListener.
I'm kind of stuck here, which Java Swing component do you think would be the most suitable in this scenario?
The text in my array may be long, so a one lined label would not be a good choice.
What other alternatives or approaches do I have?
Thank you very much, any help and suggestions are appreciated.
This is basic example is based on the suggestion posted by #Robin
public class TestDisplayString {
public static void main(String[] args) {
new TestDisplayString();
}
public TestDisplayString() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextArea textArea;
private List<String> content;
private Iterator<String> iterator;
public TestPane() {
readText();
setLayout(new BorderLayout());
textArea = new JTextArea(10, 40);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
add(new JScrollPane(textArea));
iterator = content.iterator();
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (iterator.hasNext()) {
textArea.setText(iterator.next());
} else {
((Timer)e.getSource()).stop();
}
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
protected void readText() {
content = new ArrayList<>(25);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/Text.txt")));
String text = null;
while ((text = reader.readLine()) != null) {
if (text.trim().length() > 0) {
content.add(text);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
}
}
This is the contents of the "Text.txt" file.
How to Use Swing Timers
A Swing timer (an instance of javax.swing.Timer) fires one or more
action events after a specified delay. Don't confuse Swing timers with
the general-purpose timer facility that was added to the java.util
package in release 1.3. This page describes only Swing timers.
In general, we recommend using Swing timers rather than
general-purpose timers for GUI-related tasks because Swing timers all
share the same, pre-existing timer thread and the GUI-related task
automatically executes on the event-dispatch thread. However, you
might use a general-purpose timer if you don't plan on touching the
GUI from the timer, or need to perform lengthy processing.
You can use Swing timers in two ways:
To perform a task once, after a delay.
For example, the tool tip manager uses Swing timers to determine when to show a tool tip and when to hide it.
To perform a task repeatedly.
For example, you might perform animation or update a component that displays progress toward a goal.
Swing timers are very easy to use. When you create the timer, you
specify an action listener to be notified when the timer "goes off".
The actionPerformed method in this listener should contain the code
for whatever task you need to be performed. When you create the timer,
you also specify the number of milliseconds between timer firings. If
you want the timer to go off only once, you can invoke
setRepeats(false) on the timer. To start the timer, call its start
method. To suspend it, call stop.
Note that the Swing timer's task is performed in the event dispatch
thread. This means that the task can safely manipulate components, but
it also means that the task should execute quickly. If the task might
take a while to execute, then consider using a SwingWorker instead of
or in addition to the timer. See Concurrency in Swing for instructions
about using the SwingWorker class and information on using Swing
components in multi-threaded programs.
Let's look at an example of using a timer to periodically update a
component. The TumbleItem applet uses a timer to update its display at
regular intervals. (To see this applet running, go to How to Make
Applets. This applet begins by creating and starting a timer:
timer = new Timer(speed, this); timer.setInitialDelay(pause);
timer.start();
The speed and pause variables represent applet parameters; as
configured on the other page, these are 100 and 1900 respectively, so
that the first timer event will occur in approximately 1.9 seconds,
and recur every 0.1 seconds. By specifying this as the second argument
to the Timer constructor, TumbleItem specifies that it is the action
listener for timer events.
After starting the timer, TumbleItem begins loading a series of images
in a background thread. Meanwhile, the timer events begin to occur,
causing the actionPerformed method to execute:
public void actionPerformed(ActionEvent e) {
//If still loading, can't animate.
if (!worker.isDone()) {
return;
}
loopslot++;
if (loopslot >= nimgs) {
loopslot = 0;
off += offset;
if (off < 0) {
off = width - maxWidth;
} else if (off + maxWidth > width) {
off = 0;
}
}
animator.repaint();
if (loopslot == nimgs - 1) {
timer.restart();
} }
Until the images are loaded, worker.isDone returns false, so timer
events are effectively ignored. The first part of the event handling
code simply sets values that are employed in the animation control's
paintComponent method: loopslot (the index of the next graphic in the
animation) and off (the horizontal offset of the next graphic).
Eventually, loopslot will reach the end of the image array and start
over. When this happens, the code at the end of actionPerformed
restarts the timer. Doing this causes a short delay before the
animation sequence begins again.
Use your ActionListener in combination with a javax.Swing.Timer. The ActionListener assigned to the Timer will be called on regular intervals with the specified delay.
See the timer tutorial for more information
I am making a game having squares in it (a grid of panels) and when the game ends there is an algorithm that changes the color of the panels one by one in a "live" fashion where the user watches the squares change color slowly. I try something like:
Thread.sleep(1000);
grid.getComponent(boxNumber).setBackground(Color.YELLOW);
Thread.sleep(1000);
grid.getComponent(boxNumber).setBackground(Color.ORANGE);
Although the color of a box changes to Yellow, it does not change to Orange afterwards. Anyone have any ideas? Hope I was able to be clear.
Read the section from the Swing tutorial on Concurrency to understand why you should not be using the sleep() method.
One solution is to use a SwingWorker, then you can 'publish' the color of the component so it can be updated properly on the EDT and you can invoke the sleep() method in the worker as well.
These need to happen on the Swing event thread. call set background via:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
grid.getComponent(boxNumber).setBackground(Color.ORANGE);
}
});
Note, your Thread.sleep() should not be in the event thread (or directly from within a Swing event listener (ActionListener, WindowListener, etc).
It would also be prudent to look the Swing Timing Framework which is specifically for things like this.
-Generally its not a good idea to do Thread.sleep(1000); in the EDT. You should try using Timers.
-You also need to call revalidate()/validate() and repaint() afterward.
So maybe something like this:
Timer yellowTimer = new Timer(1000,new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jtp.setBackground(Color.YELLOW);
//call revalidate()/validate() and repaint() afterward
jtp.revalidate();
jtp.repaint();
}
});
yellowTimer.setRepeats(false);
Timer orangeTimer = new Timer(2000,new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jtp.setBackground(Color.ORANGE);
//call revalidate()/validate() and repaint() afterward
jtp.revalidate();
jtp.repaint();
}
});
orangeTimer.setRepeats(false);
yellowTimer.start();
orangeTimer.start();