NetBeans Forums

 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
  

How to activate the busy animation in the status bar?

 
Post new topic   Reply to topic    NetBeans Forums -> NetBeans Users
View previous topic :: View next topic  
Author Message
aznan



Joined: 03 Sep 2008
Posts: 7

PostPosted: Thu Sep 11, 2008 2:10 pm    Post subject: How to activate the busy animation in the status bar? Reply with quote

Hi!
I've tried to figure out how to activate/deactivate the spinning circle down next to the progress bar that is created when you make a new swing application. I've studied the MarsRover example but have been unable to find the right solution. I suppose it has something to do with changing some property of something and/or sending some kind of message or other...? Razz

Can you please help me out with this?
Back to top
Daniel L
Posted via mailing list.





PostPosted: Thu Sep 11, 2008 4:24 pm    Post subject: How to activate the busy animation in the status bar? Reply with quote

This is indeed somewhat tricky to find it out... I have understood at
least some basics, and will try to explain it.

These animations are controlled by a background task. Background tasks
should be used when time consuming tasks are made, which should not
"freeze" the apllication. So a background task runs in the background,
and is firing messages every now and then, while the main programming
is still running and reacting. You can observe the task messages via a
taskmonitor and than e.g. make changes to GUI components, like in this
case the animated label (circling icon).

First of all, here is how a task is started. One way to do this is via
actions (right click on a component and choose "set action"). Then you
could start a task like this:

@Action
public Task myTask() {
return new
ThisIsMyTask
(org
.jdesktop.application.Application.getInstance(yourappsnamehere.class));
}

The above sample shows how to start a task via an action, e.g.
pressing a button. But you can also start a task manually, out of your
application, without user interaction. I recently asked this question
in this list and got following perfectly working answer:

Task mT = myTask();
ApplicationContext appC = Application.getInstance().getContext();
TaskMonitor tM = appC.getTaskMonitor();
TaskService tS = appC.getTaskService();
tS.execute(mT);
tM.setForegroundTask(mT);

This starts the task manually, by referring to the method shown in the
first sample above. So, you have to have this method anyway, as far as
I understood, but not necessarily declared as "action".


Now, the Task class itself looks like the following:

private class ThisIsMyTask extends
org.jdesktop.application.Task<Object, Void> {
ThisIsMyTask(org.jdesktop.application.Application app) {
super(app);

}

Furthermore, this class has some overidden methods. The most important
one ist "doInBackground()". This method contains the time consuming
source code, which runs in the background, while the "main
application" can still do other things (even waiting, e.g.).

@Override protected Object doInBackground() throws
IOException {
// your heavy code here
return null;
}

Two more useful methods are "succeeded" and "finished". succeeded is
called, when the task has been successfully completed. Finished is
called afterwards - but it is also called, when the task is "finished"
by a cancel action for instance.

@Override protected void succeeded(Object result) {
// what should happen if task was successfully completed?
// insert here
}

@Override
protected void finished()
{
// when the task is finished, enter your code here. this method is
even called, when
// a task was cancelled - if I understood right
super.finished();
}


Now, these are the tasks basics. Now to the animated cycling icon.

First of all, you have to store the single icons from the animations
in an array. this is what you find in the samples from NetBeans:

// initiate animated busy-icons, which are animated when the
thread is running
int busyAnimationRate =
resourceMap.getInteger("StatusBar.busyAnimationRate");
for (int i = 0; i < busyIcons.length; i++) {
busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons["
+ i + "]");
}

Than you have to create a timer, which will start the animation once
this timer is started. By creating this timer, it is not automatically
running, just initiated...

// and create a busy-icon-timer
busyIconTimer = new Timer(busyAnimationRate, new
ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
}
});


The following lines just set the icon to the statusAnimationLabel (the
one which show the cycling icon respectively a light grey one if
nothing happens)

// initiate the idle icon and make it visible
idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);


Now you have to create a task monitor, which observes the task. If I
understood correctly, it is observing the current foreground task, so
it might get in conflict with several background tasks at the same
time - BUT I'M NOT SURE WITH THIS!

// connecting action tasks to status bar via TaskMonitor
TaskMonitor taskMonitor = new
TaskMonitor
(org
.jdesktop
.application.Application.getInstance(yourapp.class).getContext());

taskMonitor.addPropertyChangeListener(new
java.beans.PropertyChangeListener() {
@Override
public void propertyChange(java.beans.PropertyChangeEvent
evt) {
String propertyName = evt.getPropertyName();


And now come the events or messages which are fired by the background
tasks. Here you decide, *what* should be done in such a case.

If I understood correctly, the "start" message is automatically fired
by the task. So everything here will be done automatically when the
background thread starts. In this case, the timer of the cycling icon
is started, i.e. the icon is animated, and the progressbar is made
visible (but not animated! there is no timer for the progressbar, it
is just made visible; we come back to this later)

// when a background thread starts, start the busy
icon animation
if ("started".equals(propertyName)) {
if (!busyIconTimer.isRunning()) {
statusAnimationLabel.setIcon(busyIcons[0]);
busyIconIndex = 0;
busyIconTimer.start();
}
// and make the progressbar visible
progressBar.setVisible(true);
progressBar.setIndeterminate(true);


On the opposite, when the task is done, the "done" message is
automatically fired. Accordingly, here the cycling icon timer is
stopped and the progressbar is hidden

// when the thread finished working, stop animation,
set idle icon
// and hide the progress bar
} else if ("done".equals(propertyName)) {
busyIconTimer.stop();
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);
progressBar.setValue(0);

Now here comes a message which can be fired by your application, that
means you can let this event happen. for instance, you can tell the
task monitor out of your background task(!) that it is proceeding,
i.e. firing a "progress" message. when the task monitor gets this
message from your background task, you can insert your code here what
should be done. typically, the progressbar is animated.

// if a progress was indicated during the thread
using the
// "setProgress(value,min,max)" method, we can change
the state
// of the progress bar here.
} else if ("progress".equals(propertyName)) {
int value = (Integer)(evt.getNewValue());
progressBar.setVisible(true);
progressBar.setIndeterminate(false);
progressBar.setValue(value);
}
}
});
}
}


As you see, we have to important components here: statusAnimationLabel
and progressBar. I don't use the statusMessageLabel, so it's missing
here.

Now, once the background task is started (see very above), the icon is
automatically animated, because we have started a timer which is
responsible for the animation. but: the progressbar is only "animated"
when we fire a progress event, which does not occur automatically -
unlike "start" and "done" events/messages.

The "progress" event/message for the taskmonitor is simply fired when
invoking the "setProgress" method!

This is what you could put in your doInBackground-Method in your task.
Here's an example for loading a file and animating the progressbar
which show the process of the amount of loaded bytes:

// length of file
final long l = filepath.length();
// length of file in kilobytes
final long kbl = l / 1024;
// counter for progbar
long counter = 0;

fr = new FileReader(filepath);
buffer = new StringBuffer("");

for (int c; (c=fr.read()) != -1Wink {
// append the bytes to the buffer
buffer.append((char)c);
// increase the counter for the progress
bar
counter++;
// this method fires the "progress" event/message for the task
monitor
setProgress(counter/1024,0,kbl);


that's it. all your time consuming stuff should be put into the
doInBackground method. If you like, you can animate a progress bar, if
you don't do this, you just have the cycling icon.

Now, since the initialization of the animated icons and progressbar
needs known GUI components, usually all the init stuff is included in
that class that contains also the components (statusMessageLabel,
progressBar). But since I'm writing a desktop application which uses
several forms with background tasks, I simply created an "task monitor
initialisation class". Whenever I have a form which needs background
tasks, I simply pass the JLabel (statusAnimationLabel) and
JProgressBar (progressbar) as parameters to the constructor:

CInitStatusBar isb = new
CInitStatusBar( statusAnimationLabel, progressBar );

Now I only need to write my Task Class and start the task via an
action or manually. But I don't need to have the init stuff also
included.

Here's the complete class with the "externalised" taskmonitor-init:

public class CInitStatusBar {

private final Timer busyIconTimer;
private final Icon idleIcon;
private final Icon[] busyIcons = new Icon[15];
private int busyIconIndex = 0;

org.jdesktop.application.ResourceMap resourceMap =
org
.jdesktop
.application
.Application
.getInstance
(zettelkasten
.ZettelkastenApp
.class).getContext().getResourceMap(ZettelkastenView.class);

/**
* Initiates the status bar for background tasks.
* Catches messages from the doInBackground task
* and changes the progressbar state, the busy icon animation
* and - if necessary - the status message.
*/
CInitStatusBar( final javax.swing.JLabel statusAnimationLabel,
final javax.swing.JProgressBar progressBar ) {
/**
* This is pre-defined code taken from the NetBeans IDE
* Initiates some basic things for background tasks, like
* associating a statusbar and busy-icon to a background thread
*/

// initiate animated busy-icons, which are animated when the
thread is running
int busyAnimationRate =
resourceMap.getInteger("StatusBar.busyAnimationRate");
for (int i = 0; i < busyIcons.length; i++) {
busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons["
+ i + "]");
}
// and create a busy-icon-timer
busyIconTimer = new Timer(busyAnimationRate, new
ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
}
});

// initiate the idle icon and make it visible
idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);

// connecting action tasks to status bar via TaskMonitor
TaskMonitor taskMonitor = new
TaskMonitor
(org
.jdesktop
.application
.Application
.getInstance(zettelkasten.ZettelkastenApp.class).getContext());

taskMonitor.addPropertyChangeListener(new
java.beans.PropertyChangeListener() {
@Override
public void propertyChange(java.beans.PropertyChangeEvent
evt) {
String propertyName = evt.getPropertyName();
// when a background thread starts, start the busy
icon animation
if ("started".equals(propertyName)) {
if (!busyIconTimer.isRunning()) {
statusAnimationLabel.setIcon(busyIcons[0]);
busyIconIndex = 0;
busyIconTimer.start();
}
// and make the progressbar visible
progressBar.setVisible(true);
progressBar.setIndeterminate(true);
// when the thread finished working, stop animation,
set idle icon
// and hide the progress bar
} else if ("done".equals(propertyName)) {
busyIconTimer.stop();
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);
progressBar.setValue(0);
// if a progress was indicated during the thread
using the
// "setProgress(value,min,max)" method, we can change
the state
// of the progress bar here.
} else if ("progress".equals(propertyName)) {
int value = (Integer)(evt.getNewValue());
progressBar.setVisible(true);
progressBar.setIndeterminate(false);
progressBar.setValue(value);
}
}
});
}
}


I hope I could help.

Best wishes
Daniel

Am 11.09.2008 um 16:10 schrieb aznan:

Quote:
Hi!

I've tried to figure out how to activate/deactivate the spinning
circle down next to the progress bar that is created when you make a
new swing application. I've studied the MarsRover example but have
been unable to find the right solution. I suppose it has something
to do with changing some property of something and/or sending some
message or other...? :P



Can you please help me out with this?




--
Daniel L
Back to top
aznan



Joined: 03 Sep 2008
Posts: 7

PostPosted: Fri Sep 12, 2008 6:34 am    Post subject: Reply with quote

Wow. That is one humongous answer!

Extremely detailed and thorough. Thank you so much for this! Will try it out right away.
Back to top
glaursen69



Joined: 23 Sep 2009
Posts: 8

PostPosted: Fri Feb 12, 2010 12:06 am    Post subject: Reply with quote

I was able to accomplish this by using JQuery. Include the current version of JQuery and BlockUI and there are several cool progress and blocking effects that you can use.
Back to top
aznan



Joined: 03 Sep 2008
Posts: 7

PostPosted: Fri Feb 12, 2010 7:23 am    Post subject: Reply with quote

Isn't JQuery a javascript library? How were you able to incorporate that into Swing? Or where you talking about something else?
Back to top
glaursen69



Joined: 23 Sep 2009
Posts: 8

PostPosted: Fri Feb 12, 2010 4:36 pm    Post subject: Reply with quote

Sorry...didn't see that it was a Swing application. I included JQuery in my JSP and created a function that I call for the onClick event of a button/hyperlink/etc. I get a nice popup processing window with the webpage disabled in the background until the processing is complete and I get a response and the page refreshes.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    NetBeans Forums -> NetBeans Users All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo