Appending Text to a TextArea over time (with delay) - java

I have a TextArea that I would like to be able to append characters or words to over a period of time. I tried using Thread.sleep() but then quickly realized this was horribly wrong.
I guess in pseudo-pseudocode
textArea.appendText("hey");
mysteryWaitMethod(500);
textArea.appendText("delayed");

JavaFX does have a timer built in - it's called a Timeline. It's simple, straightforward, and provides extra functionality like Swing's Timer class, and, most importantly, executes code on the UI thread.
I don't know much about JavaFX directly, but generally you want things that modify the UI executing on the UI thread. That's what this class does... I'd recommend using it over java.util.Timer (use that for background tasks... not UI ones). When multiple threads try to mess with a UI, bad things tend to happen (which is the reason for these timers).
This post provides a good example of how to use it: https://stackoverflow.com/a/9966213/1515592

Use the javax.swing.Timer
textArea.appendText("hey");
int delay = 500; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
textArea.appendText("delayed");
}
};
Timer t = new Timer(delay, taskPerformer);
t.setRepeats(false);
t.start();
http://docs.oracle.com/javase/6/docs/api/javax/swing/Timer.html
Or java.util.Timer
new Timer().schedule(
new TimerTask() {
#Override
public void run() {
textArea.appendText("delayed");
}
}, 500);
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html

Related

Why does this code keep looping? ( concept of ActionListener)

I'm a bit lost on this. So here's some code for an ActionListener:
public static void main(String[] args)
{
ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent event){
System.out.println("hello");
}
};
Timer displayTimer = new Timer(5000, listener);
displayTimer.start();
}
And it prints hello over and over... I don't quite understand. why doesn't it just print once?
thanks
Because you are using a Timer and haven't called displayTimer.setRepeats(false);
However, I recommend using a ExecutorService instead of Timer. See this question. There are a few things that a Timer in Java is lacking, see this question which will also help you setup an ExecutorService that will behave just like a Timer that you are used to.
As the documentation to (Timer)[http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html] says, your constructor initializes the timer with both an initial delay and a between-event delay of five seconds. The timer thus executes your ActionListener every five seconds.

Stopping a Swing timer when a component is hidden

I have a Swing timer (javax.swing.Timer) which is used to perform some animation within a custom Swing component.
However, this is causing problems - in particular it seems to stop the application from terminating because of the live timer thread even after all windows are closed. Also it would be nice to avoid the overhead of timers running on hidden objects when the animation cannot be seen.
Ideally I'd like to do the following:
Stop the timer when the component is hidden
Start the time again whenever the component becomes visible
Is this possible to do (in a thread-safe way of course!)
I am skeptical of your first premise: this simple counter-example shows that a running javax.swing.Timer does not preclude EXIT_ON_CLOSE. The package-private, shared javax.swing.TimerQueue starts a daemon thread, which allows Program Exit. You may be understandably reluctant to rely on this implementation detail, but it may be worth looking for another reason your program fails to exit.
If defer to #kleopatra on AncestorListener; it should allow you to control the Timer as desired. The duty cycle of a component animation is typical fairly light, and it's usually dominated by rendering; the latter's overhead is small when the component is not visible. It may be worth profiling to verify that the proposed optimization is worth the effort. If so, consider a WindowListener to minimize activity in an inactive or iconified window.
Addendum: A now deleted answer suggested overriding setVisible() to condition the timer. While superficially appealing, the approach is brittle and scales poorly. The listener approach leverages the observer pattern commonly used in Swing architecture.
The event queue should be quiet for one second for the shutdown to be initialized. That is a hard-coded value in AWTAutoShutdown class.
So if your swing timer keeps generating events, less then a second apart, that would keep the application from terminate.
Look at this example (below). It would not terminate, because the thread, even though it marked as deamon, keeps adding events to the queue. If we increase the sleep to 1500 (1.5 seconds) - it would terminate happily.
public static void main(String[] args)
{
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
while (true)
{
// Submit an empty event to the queue
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
}
});
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
throw new IllegalStateException(e);
}
}
}
});
thread.setDaemon(true);
thread.start();
}
We do it like this:
private static final class DisplayabilityListener implements HierarchyListener {
private final JComponent component;
private final Timer timer;
private DisplayabilityListener(JComponent component, Timer timer) {
this.component = component;
this.timer = timer;
}
#Override
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) > 0) {
if (component.isDisplayable()) {
timer.start();
} else {
timer.stop();
}
}
}
}

Basic second timer implementation

I am very new to the android platform thus java so i have a pretty basic question i am trying to make a simple second timer so here is the code i have written. I don't know why but the method run never gets executed:
Timer tmr = new Timer();
tmr.schedule(new TimerTask()
{
#Override
public void run() {
TextView txt = (TextView) findViewById(R.id.txtLoading);
counter++;
txt.setText(counter);
}
}, 1000);
LE : actually it looks like it executing but the GUI doesn't get updated ... why ?
Using Timer like that creates a new Thread, and updating the GUI from a thread which is not the main thread is not a good idea.
A better approach is the one reported in this link: http://developer.android.com/resources/articles/timed-ui-updates.html
Hope it helps!
I guess that is because you are not working in your UI thread. Read about UI threads here.
You might want to consider using AsyncTask that takes care of all the UI thread syncronisation stuff ;)
change your code like this
Timer tmr = new Timer();
tmr.schedule(new TimerTask()
{
#Override
public void run() {
Log.w("this", "is 1");
}
},1000, 1000);

call a method at a specified time

How can I call a method every n seconds?
I want to do a slideshow with Swing and CardLayout and every n seconds
it must show a different image calling a different method
import java.util.*;
class MyTimer extends TimerTask
{
public void run()
{
//change image
}
}
then in your main you can schedule the task:
Timer t = new Timer();
t.schedule(new MyTimer(), 0, 5000);
first number is initial delay, second is the time between calls to run() of your TimerTask: 5000 is 5 seconds.
As BalusC noted usually you dispatch swing changes on AWT event thread. In this simple cause it shouldn't create problems when changing background from an outside thread, in any case you should use
public static void SwingUtilities.invokeLater(Runnable whatToExecute)
to dispatch your change on the right thread.
If you prefer BalusC approach just use an ActionListener:
public void BackgroundChange implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//change bg
}
}
javax.swing.Timer t = new javax.swing.Timer(5000, new BackgroundChange());
They both provide same functionality, but this later one is already prepared to work out together with Swing threads mantaining compatibility and avoiding strange synchronizations issues.
Since you're using Swing, you would like to use javax.swing.Timer for this. Here's a Sun tutorial on the subject.
For any more than trivial animation in Swing app, check out Trident: http://kenai.com/projects/trident/pages/Home

Java - repaint component every second?

I would like to repaint component after each second, but it didn't work. What I am trying is:
try{
while(true){
Thread.currentThread().sleep(1000);
gc.cb.next();
gc.repaint();
}
}
catch(Exception ie){
}
I would advise using a javax.swing.Timer for this problem, which will periodically fire an ActionEvent on the Event Dispatch thread (note that you should only call repaint and / or manipulate Swing components from this thread). You can then define an ActionListener to intercept the event and repaint your component at this point.
Example
JComponent myComponent = ...
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
myComponent.repaint();
}
};
new Timer(delay, taskPerformer).start();
Also note that SwingWorker is probably inappropriate as it is typically used for background tasks that have a defined start and end, rather than a periodic task.
Make sure you're not hogging the UI-thread for this. If you're executing this loop in the UI-thread, then the repaint event will never be dispatched.
Another note; sleep is a static method, and should be invoked as Thread.sleep(...). (There is no way of doing thatThread.sleep(...) anyway.)
The "correct" way of doing this is probably to use a SwingWorker. Have a look at the tutorial.
If you provide more code, we can provide better answers.

Categories