柱状图(Bar Chart),一种带有矩形条(Rectangular bar)的双轴图表,Rectangular bar可以水平放置也可以竖垂直放置。
每个Bar的长度与图表表示的特定数据是成比例的。Bar Chart一般用来展示散列数据。你可以使用多组Bar来分类绘制数据
例子:
创建Bar Chart
要在你的JavaFX应用程序中创建Bar Chart,需要创建两个坐标轴、实例化BarClass类、定义数据序列并且把数据指定给Bar Chart。例创建了一个有三组数据的Bar Chart来表示5个国家的金融数据。每个国家的数据被当作一个分类以水平坐标轴上的一组Bar来展示
BarChart类有两个属性分别控制着两个Category数据的间距和同Category数据中两个Bar之间的间距。使用barGap和categoryGap属性来使图表中的Bar更好地分布。例使用setBarGap和setCategoryGap方法来为这两个属性设置了特定的值。
例 设置Bar之间和Category之间的间距
bc.setBarGap(3);
bc.setCategoryGap(20);
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class BarChartSample extends Application {
@Override public void start(Stage stage) {
stage.setTitle("柱状统计图");
final NumberAxis yAxis = new NumberAxis();//定义一个数字轴起名为y轴
final CategoryAxis xAxis = new CategoryAxis();//定义一个分类轴起名为x轴
final BarChart<String,Number> bc =
new BarChart<>(xAxis,yAxis);//创建一个柱状图(条形图)
bc.setTitle("mxc值");//设置图的标题
xAxis.setLabel("圈子");//设置x轴标签
yAxis.setLabel("总值");//设置y轴标签
XYChart.Series series1 = new XYChart.Series();//创建数据序列1
series1.setName("m");//序列标识
series1.getData().add(new XYChart.Data("天朝",888996 ));//设置数据序列值
series1.getData().add(new XYChart.Data("漂亮国",995820));//设置数据序列值
series1.getData().add(new XYChart.Data("大鹅", 568212));//设置数据序列值
XYChart.Series series2 = new XYChart.Series();//创建数据序列2
series2.setName("x");//序列标识
series2.getData().add(new XYChart.Data("天朝",898996 ));//设置数据序列值
series2.getData().add(new XYChart.Data("漂亮国",925820));//设置数据序列值
series2.getData().add(new XYChart.Data("大鹅", 60212));//设置数据序列值
XYChart.Series series3 = new XYChart.Series();//创建数据序列2
series3.setName("c");//序列标识
series3.getData().add(new XYChart.Data("天朝",898996 ));//设置数据序列值
series3.getData().add(new XYChart.Data("漂亮国",925820));//设置数据序列值
series3.getData().add(new XYChart.Data("大鹅", 60212));//设置数据序列值
Scene scene = new Scene(bc,800,600);//创建场景,场景上挂载柱状图对象bc
bc.getData().addAll(series1, series2,series3);//柱状图对象上挂载3个数据序列
stage.setScene(scene);//舞台上挂载场景
stage.show();//舞台展现
}
public static void main(String[] args) {
launch(args);
}//启动javaFX程序
}
——————————————————————————————
水平柱状图(Horizontal Bar Chart)
通过为纵轴定义Category将Bar Chart的方向由垂直变为水平。将横轴定义为NumberAxis类型,纵轴定义为CategoryAxis类型。不要忘了修改BarChart对象的声明
/**
* @author zhaoyong
* @Date 2022/5/18
* @Description
*/
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class BarChartTest extends Application {
final static String austria = "澳大利亚";
final static String brazil = "巴西";
final static String france = "法国";
final static String italy = "意大利";
final static String usa = "美国";
@Override
public void start(Stage stage) {
stage.setTitle("水平柱状图例子");
final NumberAxis xAxis = new NumberAxis();
final CategoryAxis yAxis = new CategoryAxis();
final BarChart<Number, String> bc =
new BarChart<>(xAxis, yAxis);
bc.setTitle("国家篮球队技术统计");
xAxis.setLabel("技术能力");
xAxis.setTickLabelRotation(90);
yAxis.setLabel("国家");
XYChart.Series series1 = new XYChart.Series();
series1.setName("防守能力");
series1.getData().add(new XYChart.Data(25601.34, austria));
series1.getData().add(new XYChart.Data(20148.82, brazil));
series1.getData().add(new XYChart.Data(10000, france));
series1.getData().add(new XYChart.Data(35407.15, italy));
series1.getData().add(new XYChart.Data(12000, usa));
XYChart.Series series2 = new XYChart.Series();
series2.setName("体力");
series2.getData().add(new XYChart.Data(57401.85, austria));
series2.getData().add(new XYChart.Data(41941.19, brazil));
series2.getData().add(new XYChart.Data(45263.37, france));
series2.getData().add(new XYChart.Data(117320.16, italy));
series2.getData().add(new XYChart.Data(14845.27, usa));
XYChart.Series series3 = new XYChart.Series();
series3.setName("进攻能力");
series3.getData().add(new XYChart.Data(45000.65, austria));
series3.getData().add(new XYChart.Data(44835.76, brazil));
series3.getData().add(new XYChart.Data(18722.18, france));
series3.getData().add(new XYChart.Data(17557.31, italy));
series3.getData().add(new XYChart.Data(92633.68, usa));
Scene scene = new Scene(bc, 800, 600);
bc.getData().addAll(series1, series2, series3);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
需要注意上面调用了横轴的setTickLabelRotation方法来旋转Label以使文字更加易读
水平柱状图在你想要表示排名数据时会很有用
——————————————————
创建堆叠柱状图(Stacked Bar Chart)
Bar Chart中属于同一个Category的Bar都堆叠起来。使用StackedBarChart类来完成
创建Stacked Bar Chart
/**
* @author zhaoyong
* @Date 2022/5/18
* @Description
*/
import java.util.Arrays;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class StackedBarChartSample extends Application {
final static String magician = "法师";
final static String fighter = "战士";
final static String hunter = "猎人";
final static String thief = "盗贼";
final static String doctor = "医疗师";
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final StackedBarChart<String, Number> sbc =
new StackedBarChart<>(xAxis, yAxis);
final XYChart.Series<String, Number> series1 =
new XYChart.Series<>();
final XYChart.Series<String, Number> series2 =
new XYChart.Series<>();
final XYChart.Series<String, Number> series3 =
new XYChart.Series<>();
@Override
public void start(Stage stage) {
stage.setTitle("堆叠柱状图");
sbc.setTitle("角色能力");
xAxis.setLabel("Country");
xAxis.setCategories(FXCollections.<String>observableArrayList(
Arrays.asList(magician, fighter, hunter, thief, doctor)));
yAxis.setLabel("Value");
series1.setName("防守能力");
series1.getData().add(new XYChart.Data<>(magician, 20));
series1.getData().add(new XYChart.Data<>(fighter, 80));
series1.getData().add(new XYChart.Data<>(hunter, 40));
series1.getData().add(new XYChart.Data<>(thief, 20));
series1.getData().add(new XYChart.Data<>(doctor, 10));
series2.setName("攻击能力");
series2.getData().add(new XYChart.Data<>(magician, 80));
series2.getData().add(new XYChart.Data<>(fighter, 60));
series2.getData().add(new XYChart.Data<>(hunter, 65));
series2.getData().add(new XYChart.Data<>(thief, 50));
series2.getData().add(new XYChart.Data<>(doctor, 10));
series3.setName("生命能力");
series3.getData().add(new XYChart.Data<>(magician, 20));
series3.getData().add(new XYChart.Data<>(fighter, 50));
series3.getData().add(new XYChart.Data<>(hunter, 55));
series3.getData().add(new XYChart.Data<>(thief, 70));
series3.getData().add(new XYChart.Data<>(doctor, 100));
Scene scene = new Scene(sbc, 800, 600);
sbc.getData().addAll(series1, series2, series3);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
——————————————————
Stacked Bar Chart定义坐标轴时,你必须要明确地把数据Category指定给某一个坐标轴。例中,通过使用setCategories方法将Category指定给横轴
Stacked Bar Chart中的区域展示了横轴上任意点在纵轴上的累加值
当你在程序中使用Bar Chart时,请记住BarChart和StackedBarChart中纵轴上的数据表示的含义是不一样的。要根应用据程序需求来选择最恰当的图表类型
你可以通过调用setCategoryGap方法来指定两个Stacked Category之间的距离
sbc.setCategoryGap(50)
让图表中的数据动起来
动画时间线并且创建了Key Frames来随机为Bar Chart的数据设置X值。时间线在程序开始时开始,并且在auto-reverse模式中无限的继续下去
Bar Chart中的动画数据
示例代码
/**
* @author zhaoyong
* @Date 2022/5/18
* @Description
*/
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BarChartTest extends Application {
final static String austria = "澳大利亚";
final static String brazil = "巴西";
final static String france = "法国";
final static String italy = "意大利";
final static String usa = "美国";
@Override
public void start(Stage stage) {
stage.setTitle("水平柱状图例子");
final NumberAxis xAxis = new NumberAxis();
final CategoryAxis yAxis = new CategoryAxis();
final BarChart<Number, String> bc =
new BarChart<>(xAxis, yAxis);
bc.setTitle("国家篮球队技术统计");
xAxis.setLabel("技术能力");
xAxis.setTickLabelRotation(90);
yAxis.setLabel("国家");
XYChart.Series series1 = new XYChart.Series();
series1.setName("防守能力");
series1.getData().add(new XYChart.Data(25601.34, austria));
series1.getData().add(new XYChart.Data(20148.82, brazil));
series1.getData().add(new XYChart.Data(10000, france));
series1.getData().add(new XYChart.Data(35407.15, italy));
series1.getData().add(new XYChart.Data(12000, usa));
XYChart.Series series2 = new XYChart.Series();
series2.setName("体力");
series2.getData().add(new XYChart.Data(57401.85, austria));
series2.getData().add(new XYChart.Data(41941.19, brazil));
series2.getData().add(new XYChart.Data(45263.37, france));
series2.getData().add(new XYChart.Data(117320.16, italy));
series2.getData().add(new XYChart.Data(14845.27, usa));
XYChart.Series series3 = new XYChart.Series();
series3.setName("进攻能力");
series3.getData().add(new XYChart.Data(45000.65, austria));
series3.getData().add(new XYChart.Data(44835.76, brazil));
series3.getData().add(new XYChart.Data(18722.18, france));
series3.getData().add(new XYChart.Data(17557.31, italy));
series3.getData().add(new XYChart.Data(92633.68, usa));
Scene scene = new Scene(bc, 800, 600);
bc.getData().addAll(series1, series2, series3);
yAxis.setAnimated(false);
Timeline tl = new Timeline();//创建一个时间线对象
tl.getKeyFrames().add(new KeyFrame(Duration.millis(500),
(ActionEvent actionEvent) -> {//每当过去500毫秒作为激发事件,并调用如下事件响应回调函数体内容
bc.getData().stream().forEach((series) -> {//lamda表达式
series.getData().stream().forEach((data) -> {//lamda表达式,每个数据序列下的数据轴上的数据随机取数变换
data.setXValue(Math.random() * 1000);
});
});
}
));
tl.setCycleCount(Animation.INDEFINITE);//无线循环次数播放效果
tl.setAutoReverse(true);//自动翻转
tl.play();//开始播放动画执行
stage.setScene(scene);//舞台上挂载场景
stage.show();//舞台展现
}
public static void main(String[] args) {
launch(args);
}
}
再次编译运行程序,你将看到坐标轴和绘制区域都会平滑地变化来适应Bar新的范围和长度。这是由Chart和Axis类的animated属性所致。该属性值默认为true来使任何数据改变都以动画形式展现
当纵轴上的数据是以Category的形式表示并且不会改变时,你可以禁止该轴上的数据动画,以此来避免国家label的闪烁
管理数据变化的动画
Java
yAxis.setAnimated(false);
/** * @author zhaoyong
* @Date 2022/5/18
* @Description
*/
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BarChartTest extends Application {
final static String austria = "澳大利亚";
final static String brazil = "巴西";
final static String france = "法国";
final static String italy = "意大利";
final static String usa = "美国";
@Override
public void start(Stage stage) {
stage.setTitle("水平柱状图例子");
final NumberAxis xAxis = new NumberAxis();
final CategoryAxis yAxis = new CategoryAxis();
final BarChart<Number, String> bc =
new BarChart<>(xAxis, yAxis);
bc.setTitle("国家篮球队技术统计");
xAxis.setLabel("技术能力");
xAxis.setTickLabelRotation(90);
yAxis.setLabel("国家");
XYChart.Series series1 = new XYChart.Series();
series1.setName("防守能力");
series1.getData().add(new XYChart.Data(25601.34, austria));
series1.getData().add(new XYChart.Data(20148.82, brazil));
series1.getData().add(new XYChart.Data(10000, france));
series1.getData().add(new XYChart.Data(35407.15, italy));
series1.getData().add(new XYChart.Data(12000, usa));
XYChart.Series series2 = new XYChart.Series();
series2.setName("体力");
series2.getData().add(new XYChart.Data(57401.85, austria));
series2.getData().add(new XYChart.Data(41941.19, brazil));
series2.getData().add(new XYChart.Data(45263.37, france));
series2.getData().add(new XYChart.Data(117320.16, italy));
series2.getData().add(new XYChart.Data(14845.27, usa));
XYChart.Series series3 = new XYChart.Series();
series3.setName("进攻能力");
series3.getData().add(new XYChart.Data(45000.65, austria));
series3.getData().add(new XYChart.Data(44835.76, brazil));
series3.getData().add(new XYChart.Data(18722.18, france));
series3.getData().add(new XYChart.Data(17557.31, italy));
series3.getData().add(new XYChart.Data(92633.68, usa));
Scene scene = new Scene(bc, 800, 600);
bc.getData().addAll(series1, series2, series3);
yAxis.setAnimated(false);
Timeline tl = new Timeline();//创建一个时间线对象
tl.getKeyFrames().add(new KeyFrame(Duration.millis(500),
(ActionEvent actionEvent) -> {//每当过去500毫秒作为激发事件,并调用如下事件响应回调函数体内容
bc.getData().stream().forEach((series) -> {//lamda表达式
series.getData().stream().forEach((data) -> {//lamda表达式,每个数据序列下的数据轴上的数据随机取数变换
data.setXValue(Math.random() * 1000);
});
});
}
));
tl.setCycleCount(Animation.INDEFINITE);//无线循环次数播放效果
tl.setAutoReverse(true);//自动翻转
tl.play();//开始播放动画执行
stage.setScene(scene);//舞台上挂载场景
stage.show();//舞台展现
}
public static void main(String[] args) {
launch(args);
}
}