Skip to content

Instantly share code, notes, and snippets.

@nekoTheShadow
Last active March 20, 2020 01:12
Show Gist options
  • Save nekoTheShadow/469fc62d0d1a355c2b5a4210688665d1 to your computer and use it in GitHub Desktop.
Save nekoTheShadow/469fc62d0d1a355c2b5a4210688665d1 to your computer and use it in GitHub Desktop.
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
public static void main(String[] args) throws IOException {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
// 棒グラフ用のデータを用意する。データには0以上の整数を指定すること。
Series<String, Number> series1 = new Series<>();
series1.getData().add(new Data<>("2020-1Q", 651));
series1.getData().add(new Data<>("2020-2Q", 1440));
series1.getData().add(new Data<>("2020-3Q", 260));
series1.getData().add(new Data<>("2020-4Q", 390));
series1.getData().add(new Data<>("2021-1Q", 110));
series1.getData().add(new Data<>("2021-2Q", 1168));
series1.getData().add(new Data<>("2021-3Q", 910));
series1.getData().add(new Data<>("2021-4Q", 1220));
series1.getData().add(new Data<>("2022-1Q", 525));
series1.getData().add(new Data<>("2022-2Q", 780));
series1.getData().add(new Data<>("2022-3Q", 1304));
series1.getData().add(new Data<>("2022-4Q", 1042));
// 線グラフ用のデータを用意する。データには0以上の整数を指定すること。
Series<String, Number> series2 = new Series<>();
series2.getData().add(new Data<>("2020-1Q", 27));
series2.getData().add(new Data<>("2020-2Q", 13));
series2.getData().add(new Data<>("2020-3Q", 48));
series2.getData().add(new Data<>("2020-4Q", 61));
series2.getData().add(new Data<>("2021-1Q", 80));
series2.getData().add(new Data<>("2021-2Q", 79));
series2.getData().add(new Data<>("2021-3Q", 7));
series2.getData().add(new Data<>("2021-4Q", 45));
series2.getData().add(new Data<>("2022-1Q", 74));
series2.getData().add(new Data<>("2022-2Q", 37));
series2.getData().add(new Data<>("2022-3Q", 20));
series2.getData().add(new Data<>("2022-4Q", 56));
// x軸とy軸の設定を行う。棒グラフは左、線グラフは右にy軸を設定する。
CategoryAxis xAxis = new CategoryAxis();
NumberAxis yAxis1 = newYAxis(series1);
NumberAxis yAxis2 = newYAxis(series2);
yAxis1.setLabel("棒グラフ");
yAxis2.setLabel("線グラフ");
yAxis1.setSide(Side.LEFT);
yAxis2.setSide(Side.RIGHT);
int sizeX = 800;
int sizeY = 800;
int offsetX = 50;
// 棒グラフを作成する。
BarChart<String, Number> chart1 = new BarChart<>(xAxis, yAxis1);
chart1.getData().add(series1);
chart1.setAnimated(false);
chart1.setLegendVisible(false);
chart1.setLayoutX(0);
chart1.setTranslateX(0);
chart1.setMaxWidth(sizeX - offsetX);
// 線グラフを作成する。ここでは棒グラフの上に線グラフを重ねるため、下となる棒グラフが見えるような設定を行う必要がある。
LineChart<String, Number> chart2 = new LineChart<>(xAxis, yAxis2);
chart2.getData().add(series2);
chart2.setAnimated(false);
chart2.setLegendVisible(false);
chart2.setLayoutX(0);
chart2.setTranslateX(offsetX);
chart2.setMaxWidth(sizeX - offsetX);
chart2.setHorizontalGridLinesVisible(false);
chart2.setVerticalGridLinesVisible(false);
chart2.lookup(".chart-plot-background").setStyle("-fx-background-color: transparent;");
chart2.lookup(".chart-series-line").setStyle("-fx-stroke: green;");
chart2.lookupAll(".chart-line-symbol").forEach(node -> node.setStyle("-fx-background-color: green, green;"));
// 棒グラフの上に線グラフを重ねる。
StackPane pane = new StackPane();
pane.getChildren().addAll(chart1, chart2);
pane.setAlignment(Pos.BOTTOM_LEFT);
// pngファイルを生成する。
Scene scene = new Scene(pane, sizeX, sizeY);
WritableImage image = scene.snapshot(null);
File output = new File("app.png");
ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", output);
System.exit(0);
}
private NumberAxis newYAxis(Series<String, Number> series) {
ObservableList<Data<String, Number>> data = series.getData();
long n = data.size();
long max = data.stream().mapToLong(v -> (int)v.getYValue()).max().getAsLong();
long tickUnit = (max % n == 0) ? max / n : max / n + 1;
return new NumberAxis(0, tickUnit * (n+1), tickUnit);
}
}
@nekoTheShadow
Copy link
Author

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>neko.the.shadow</groupId>
  <artifactId>chart-sample</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
    <dependency>
      <groupId>org.openjfx</groupId>
      <artifactId>javafx-controls</artifactId>
      <version>11</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-swing -->
    <dependency>
      <groupId>org.openjfx</groupId>
      <artifactId>javafx-swing</artifactId>
      <version>11</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.8.0</version>
         <configuration>
           <release>11</release>
         </configuration>
      </plugin>

      <plugin>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-maven-plugin</artifactId>
        <version>0.0.4</version>
        <configuration>
          <mainClass>App</mainClass>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment