Meters are used to report progress to the user, generally the completion percentage of a background task such as a file load operation. An example is shown below. Clicking the Start button initiates a background task that simulates a long-running operation. Periodically, the task updates the meter to reflect its progress:
The BXML source for the example is shown below:
<progress:Meters title="Meters" maximized="true" xmlns:bxml="http://pivot.apache.org/bxml" xmlns:progress="org.apache.pivot.tutorials.progress" xmlns="org.apache.pivot.wtk"> <TablePane> <columns> <TablePane.Column width="1*"/> </columns> <TablePane.Row height="1*"> <Border styles="{padding:2}"> <BoxPane styles="{horizontalAlignment:'center', verticalAlignment:'center'}"> <Label text="Progress:"/> <Meter bxml:id="meter" preferredWidth="200" preferredHeight="16"/> </BoxPane> </Border> </TablePane.Row> <TablePane.Row height="-1"> <BoxPane styles="{horizontalAlignment:'center', padding:6}"> <PushButton bxml:id="progressButton" styles="{minimumAspectRatio:3}"/> </BoxPane> </TablePane.Row> </TablePane> </progress:Meters>
The Java source is as follows. The main window class defines an inner class that extends the org.apache.pivot.util.concurrent.Task class to simulate a background operation. This task simply sleeps for 100ms at a time and updates the meter when it wakes up to reflect the current count. Since all UI updates must be performed on the UI thread, the task queues a callback to set the meter's percent complete; a org.apache.pivot.wtk.TaskAdapter is used to process the task notifications for the same reason:
package org.apache.pivot.tutorials.progress; import java.net.URL; import org.apache.pivot.beans.Bindable; import org.apache.pivot.collections.Map; import org.apache.pivot.util.Resources; import org.apache.pivot.util.concurrent.Task; import org.apache.pivot.util.concurrent.TaskExecutionException; import org.apache.pivot.util.concurrent.TaskListener; import org.apache.pivot.wtk.ApplicationContext; import org.apache.pivot.wtk.Button; import org.apache.pivot.wtk.ButtonPressListener; import org.apache.pivot.wtk.Meter; import org.apache.pivot.wtk.PushButton; import org.apache.pivot.wtk.TaskAdapter; import org.apache.pivot.wtk.Window; public class Meters extends Window implements Bindable { public class SampleTask extends Task<Void> { private int percentage = 0; @Override public Void execute() throws TaskExecutionException { // Simulate a long-running operation percentage = 0; while (percentage < 100 && !abort) { try { Thread.sleep(100); percentage++; // Update the meter on the UI thread ApplicationContext.queueCallback(new Runnable() { @Override public void run() { meter.setPercentage((double)percentage / 100); } }); } catch(InterruptedException exception) { throw new TaskExecutionException(exception); } } return null; } } private Meter meter = null; private PushButton progressButton = null; private SampleTask sampleTask = null; @Override public void initialize(Map<String, Object> namespace, URL location, Resources resources) { meter = (Meter)namespace.get("meter"); progressButton = (PushButton)namespace.get("progressButton"); progressButton.getButtonPressListeners().add(new ButtonPressListener() { @Override public void buttonPressed(Button button) { if (sampleTask == null) { // Create and start the simulated task; wrap it in a // task adapter so the result handlers are called on the // UI thread sampleTask = new SampleTask(); sampleTask.execute(new TaskAdapter<Void>(new TaskListener<Void>() { @Override public void taskExecuted(Task<Void> task) { reset(); } @Override public void executeFailed(Task<Void> task) { reset(); } private void reset() { // Reset the meter and button sampleTask = null; meter.setPercentage(0); updateProgressButton(); } })); } else { // Cancel the task sampleTask.abort(); } updateProgressButton(); } }); updateProgressButton(); } private void updateProgressButton() { if (sampleTask == null) { progressButton.setButtonData("Start"); } else { progressButton.setButtonData("Cancel"); } } }
Next: Activity Indicators