Skip to content

Instantly share code, notes, and snippets.

@bugabinga
Created November 4, 2014 10:49
Show Gist options
  • Save bugabinga/54ef3373623212b6b4ca to your computer and use it in GitHub Desktop.
Save bugabinga/54ef3373623212b6b4ca to your computer and use it in GitHub Desktop.
How to show progress indicators for long running GUI operations?
package com.isp.lpt.progress;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.concurrent.Task;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.effect.DropShadow;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
/**
* Testet das Auslagern von langen GUI-Operationen in JavaFx-Threads.
*
* @author okr
*
*/
public class GuiTaskExample extends Application
{
private static final Random RANDOM = new Random();
private final static int WIDTH = 100;
private final static int HEIGHT = 100;
@Override
public void start( final Stage primaryStage )
{
final Group root = new Group();
final Group circleGroup = new Group();
final ProgressIndicator indicator = new ProgressIndicator();
root.getChildren().add( circleGroup );
root.getChildren().add( indicator );
final Scene scene = new Scene( root );
final GuiTaskExample that = this;
final Task<Void> task = new Task<Void>()
{
@Override
protected Void call() throws Exception
{
try (final IntStream intStream = RANDOM.ints( 1, HEIGHT ))
{
final long maxSize = HEIGHT * WIDTH;
final Stream<Circle> circles = intStream.mapToObj( that::createCircleThing ).limit( maxSize );
//local variables must be final for lambdas
final LongProperty counter = new SimpleLongProperty( 1 );
circles.forEach( circle ->
{
updateProgress( counter.get(), maxSize );
counter.set( counter.get() + 1 );
final CountDownLatch latch = new CountDownLatch( 1 );
Platform.runLater( ( ) ->
{
circleGroup.getChildren().add( circle );
latch.countDown();
} );
try
{
latch.await();
}
catch ( final Exception e )
{
e.printStackTrace();
}
} );
final CountDownLatch latch = new CountDownLatch( 1 );
Platform.runLater( ( ) ->
{
primaryStage.sizeToScene();
root.getChildren().remove( indicator );
latch.countDown();
} );
latch.await();
return null;
}
}
};
indicator.progressProperty().bind( task.progressProperty() );
task.exceptionProperty().addListener( ( observable, oldValue, newValue ) -> newValue.printStackTrace() );
Executors.newSingleThreadExecutor().execute( task );
primaryStage.setScene( scene );
primaryStage.show();
}
private Circle createCircleThing( final int radius )
{
final Circle circle = new Circle();
circle.setRadius( RANDOM.nextInt( radius ) );
circle.setCenterX( circle.getRadius() + RANDOM.nextInt( WIDTH ) );
circle.setCenterY( circle.getRadius() + RANDOM.nextInt( HEIGHT ) );
circle.setStrokeWidth( RANDOM.nextDouble() * 4 );
circle.setStroke( randomPaint() );
circle.setFill( randomPaint() );
circle.setEffect( new DropShadow( RANDOM.nextInt( 12 ), randomPaint() ) );
return circle;
}
private Color randomPaint()
{
return Color.rgb( RANDOM.nextInt( 255 ), RANDOM.nextInt( 255 ), RANDOM.nextInt( 255 ),
RANDOM.nextDouble() );
}
public static void main( final String[] args )
{
launch( args );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment