Last active
March 18, 2017 15:14
-
-
Save bmorris591/d631b56bf4ee6ce8fe3b42227e8dcea0 to your computer and use it in GitHub Desktop.
Little JavaFX application to generate XKCD-like self descriptive image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.axis-tick-mark, | |
.axis-minor-tick-mark, | |
.chart-vertical-grid-lines, | |
.chart-horizontal-grid-lines, | |
.chart-vertical-zero-line, | |
.chart-horizontal-zero-line { | |
-fx-stroke: transparent; | |
} | |
.chart-alternative-row-fill, .chart-alternative-column-fill{ | |
-fx-fill: white; | |
} | |
.chart-plot-background { | |
-fx-background-color: white; | |
} | |
.chart-vertical-grid-lines { | |
-fx-stroke: white; | |
} | |
.chart-horizontal-grid-lines { | |
-fx-stroke: white; | |
} | |
.chart-alternative-row-fill { | |
-fx-fill: white; | |
-fx-stroke: transparent; | |
-fx-stroke-width: 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Colors of JavaFX pie chart slices. */ | |
.data0.chart-pie { | |
-fx-pie-color: white; | |
} | |
.data1.chart-pie { | |
-fx-pie-color: black; | |
} | |
.chart-pie { | |
-fx-border-color: black; | |
-fx-border-width: 2px; | |
-fx-background-color: derive(-fx-pie-color,0%); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.boris.testbench;/** | |
* Created by Boris on 18/03/2017. | |
*/ | |
import java.io.IOException; | |
import java.util.stream.Stream; | |
import javafx.animation.KeyFrame; | |
import javafx.animation.Timeline; | |
import javafx.application.Application; | |
import javafx.collections.FXCollections; | |
import javafx.collections.ObservableList; | |
import javafx.event.ActionEvent; | |
import javafx.event.EventHandler; | |
import javafx.geometry.Insets; | |
import javafx.geometry.Pos; | |
import javafx.scene.Node; | |
import javafx.scene.Scene; | |
import javafx.scene.SnapshotParameters; | |
import javafx.scene.chart.BarChart; | |
import javafx.scene.chart.CategoryAxis; | |
import javafx.scene.chart.NumberAxis; | |
import javafx.scene.chart.PieChart; | |
import javafx.scene.chart.XYChart; | |
import javafx.scene.effect.ColorAdjust; | |
import javafx.scene.image.Image; | |
import javafx.scene.image.ImageView; | |
import javafx.scene.image.PixelReader; | |
import javafx.scene.image.WritableImage; | |
import javafx.scene.layout.Background; | |
import javafx.scene.layout.BackgroundFill; | |
import javafx.scene.layout.CornerRadii; | |
import javafx.scene.layout.HBox; | |
import javafx.scene.paint.Color; | |
import javafx.scene.shape.Rectangle; | |
import javafx.stage.Stage; | |
import javafx.util.Duration; | |
import lombok.ToString; | |
public class SelfDescription extends Application { | |
public static void main(String[] args) { | |
launch(args); | |
} | |
@Override | |
public void start(Stage stage) throws IOException { | |
ColorAdjust grayscale = new ColorAdjust(); | |
grayscale.setSaturation(-1); | |
ObservableList<PieChart.Data> pieChartData = | |
FXCollections.observableArrayList( | |
new PieChart.Data("White", 50), | |
new PieChart.Data("Black", 50)); | |
final PieChart chart = new PieChart(pieChartData); | |
chart.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY))); | |
chart.setLegendVisible(false); | |
chart.getStylesheets().add("/com/boris/testbench/pie.css"); | |
final CategoryAxis xAxis = new CategoryAxis(); | |
final NumberAxis yAxis = new NumberAxis(); | |
yAxis.setTickLabelsVisible(false); | |
final BarChart<String, Number> bc = new BarChart<>(xAxis, yAxis); | |
yAxis.setLabel("Amount of black in by panel"); | |
XYChart.Series<String, Number> series1 = new XYChart.Series<>(); | |
series1.getData().add(new XYChart.Data<>("1", 0.33)); | |
series1.getData().add(new XYChart.Data<>("2", 0.33)); | |
series1.getData().add(new XYChart.Data<>("3", 0.33)); | |
bc.setLegendVisible(false); | |
bc.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY))); | |
bc.setBarGap(-1); | |
bc.setCategoryGap(50); | |
bc.getData().addAll(series1); | |
for (Node n : bc.lookupAll(".default-color0.chart-bar")) { | |
n.setStyle("-fx-bar-fill: black;"); | |
} | |
Rectangle r = new Rectangle(); | |
r.setHeight(500); | |
r.setWidth(500); | |
r.setFill(Color.WHITE); | |
r.setStroke(Color.BLACK); | |
r.setStrokeWidth(2); | |
HBox root = new HBox(); | |
root.setAlignment(Pos.CENTER); | |
root.setStyle( | |
"-fx-background-color: white;" + | |
" -fx-padding: 15px;" + | |
" -fx-spacing: 10px;" + | |
" -fx-border-color: black;" + | |
" -fx-border-insets: 10px;" + | |
" -fx-border-style: solid;" + | |
" -fx-border-width: 2px"); | |
Stream.of(chart, bc, r).forEach(n -> n.setStyle( | |
"-fx-background-color: white;" + | |
" -fx-border-color: black;" + | |
" -fx-border-style: solid;" + | |
" -fx-border-width: 2px")); | |
chart.getStylesheets().add("/com/boris/testbench/chart.css"); | |
bc.getStylesheets().add("/com/boris/testbench/chart.css"); | |
root.getChildren().addAll(chart, bc, r); | |
Scene scene = new Scene(root, Color.WHITE); | |
scene.getRoot().setEffect(grayscale); | |
stage.setTitle("Self Description"); | |
stage.setScene(scene); | |
stage.show(); | |
final ImageView recurFinal = generateLastPanel(root, scene); | |
Timeline fiveSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() { | |
WritableImage snap = null; | |
ImageView lastPanel = recurFinal; | |
@Override | |
public void handle(ActionEvent event) { | |
final BlackAndWhile total = calculate(scene.snapshot(snap)); | |
BlackAndWhile pieSnap = calculate(chart.snapshot(new SnapshotParameters(), snap)); | |
BlackAndWhile barSnap = calculate(bc.snapshot(new SnapshotParameters(), snap)); | |
BlackAndWhile recurSnap = calculate(lastPanel.snapshot(new SnapshotParameters(), snap)); | |
pieChartData.get(0).setPieValue(total.whiteRatio() * 100); | |
pieChartData.get(1).setPieValue(total.blackRatio() * 100); | |
series1.getData().get(0).setYValue(pieSnap.black / total.black); | |
series1.getData().get(1).setYValue(barSnap.black / total.black); | |
series1.getData().get(2).setYValue(recurSnap.black / total.black); | |
lastPanel = generateLastPanel(root, scene); | |
} | |
})); | |
fiveSecondsWonder.setCycleCount(Timeline.INDEFINITE); | |
fiveSecondsWonder.play(); | |
} | |
private ImageView generateLastPanel(HBox root, Scene scene) { | |
root.getChildren().remove(2); | |
Rectangle r = new Rectangle(); | |
r.setHeight(500); | |
r.setWidth(500); | |
r.setFill(Color.WHITE); | |
r.setStroke(Color.BLACK); | |
r.setStrokeWidth(2); | |
root.getChildren().add(r); | |
ImageView imageView = null; | |
for (int j = 0; j < 10; j++) { | |
WritableImage writableImage = scene.snapshot(null); | |
imageView = new ImageView(writableImage); | |
imageView.setPreserveRatio(true); | |
imageView.setFitWidth(500); | |
root.getChildren().remove(2); | |
root.getChildren().add(imageView); | |
} | |
return imageView; | |
} | |
private static BlackAndWhile calculate(final Image image) { | |
final BlackAndWhile blackAndWhile = new BlackAndWhile(); | |
final PixelReader pixelReader = image.getPixelReader(); | |
for (int j = 0; j < image.getHeight(); j++) { | |
for (int k = 0; k < image.getWidth(); k++) { | |
final Color colour = pixelReader.getColor(k, j); | |
if (colour.equals(Color.BLACK)) { | |
blackAndWhile.black++; | |
} else if (colour.equals(Color.WHITE)) { | |
blackAndWhile.white++; | |
} | |
} | |
} | |
return blackAndWhile; | |
} | |
@ToString(of = {"black", "white"}) | |
private static final class BlackAndWhile { | |
double black; | |
double white; | |
double blackRatio() { | |
return black / (black + white); | |
} | |
double whiteRatio() { | |
return white / (black + white); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment