Skip to content

Instantly share code, notes, and snippets.

@bugabinga
Created June 24, 2016 09:08
Show Gist options
  • Save bugabinga/a375f3435a867290e1b8223ee89d1a4a to your computer and use it in GitHub Desktop.
Save bugabinga/a375f3435a867290e1b8223ee89d1a4a to your computer and use it in GitHub Desktop.
Exploring Properties and Threads in JavaFx for StackOverflow Question https://stackoverflow.com/questions/38001595/javafx-only-update-binding-after-all-dependencies-are-updated
package com.isp.stackoverflow;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* https://stackoverflow.com/questions/38001595/javafx-only-update-binding-after-all-dependencies-are-updated
*
* @author okr
* @date 24.06.2016
*
*/
public class PropertiesWithThreads extends Application
{
private final ExecutorService executor = Executors.newFixedThreadPool( 2 );
private final Property<BigDecimal> a =
new SimpleObjectProperty<>( newRandomBigDecimal( ThreadLocalRandom.current(), 10 ) );
private final Property<BigDecimal> b =
new SimpleObjectProperty<>( newRandomBigDecimal( ThreadLocalRandom.current(), 10 ) );
private final Task<Void> taskAB = new Task<Void>()
{
@Override
protected Void call() throws Exception
{
while ( !isCancelled() )
{
Thread.sleep( 2000 );
System.out.println( "Updating A!" );
Platform.runLater( () -> a
.setValue( newRandomBigDecimal( ThreadLocalRandom.current(), 10 ) ) );
Thread.sleep( 2000 );
System.out.println( "Updating B!" );
Platform.runLater( () -> b
.setValue( newRandomBigDecimal( ThreadLocalRandom.current(), 10 ) ) );
}
return null;
}
};
private final ObjectBinding<BigDecimal> c = new ObjectBinding<BigDecimal>()
{
{
super.bind( a, b );
}
@Override
protected BigDecimal computeValue()
{
return a.getValue().add( b.getValue() );
}
};
private final ObjectBinding<BigDecimal> cOnlyOnBChange = new ObjectBinding<BigDecimal>()
{
{
super.bind( b );
}
@Override
protected BigDecimal computeValue()
{
return a.getValue().add( b.getValue() );
}
};
private final Task<Void> taskC = new Task<Void>()
{
@Override
protected Void call() throws Exception
{
cOnlyOnBChange.addListener( ( __, ___, newValue ) -> System.out
.println( "C changed to " + newValue ) );
return null;
}
};
BigDecimal getC()
{
return c.getValue();
}
private static BigDecimal newRandomBigDecimal( final Random random, final int precision )
{
final BigInteger n = BigInteger.TEN.pow( precision );
return new BigDecimal( newRandomBigInteger( n, random ), precision );
}
private static BigInteger newRandomBigInteger( final BigInteger n, final Random random )
{
BigInteger r;
do
{
r = new BigInteger( n.bitLength(), random );
} while ( r.compareTo( n ) >= 0 );
return r;
}
@Override
public void start( final Stage primaryStage )
{
final Label labelA = new Label();
final Label labelB = new Label();
final Label labelC = new Label();
labelA.textProperty().bind( Bindings.format( "A = %s", a ) );
labelB.textProperty().bind( Bindings.format( "B = %s", b ) );
labelC.textProperty().bind( Bindings.format( "C = %s", c ) );
final VBox root = new VBox( 16, labelA, labelB, new Separator(), labelC );
primaryStage.setScene( new Scene( root ) );
primaryStage.show();
executor.execute( taskAB );
executor.execute( taskC );
primaryStage.setOnCloseRequest( __ ->
{
executor.shutdownNow();
primaryStage.close();
} );
}
/**
* @param args ignore.
*/
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