我们将使用Java和JFreeChart插件绘制重叠柱状图和折线图的组合。
    绘制一个像这样的图:
    image.png
    首先添加POM依赖:

    1. <dependency>
    2. <groupId>jfree</groupId>
    3. <artifactId>jfreechart</artifactId>
    4. <version>1.0.13</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>jfree</groupId>
    8. <artifactId>jcommon</artifactId>
    9. <version>1.0.16</version>
    10. </dependency>

    然后绘制:

    1. package com.rit.demo.test;
    2. import java.awt.Color;
    3. import java.awt.Font;
    4. import java.io.File;
    5. import java.text.DecimalFormat;
    6. import org.jfree.chart.ChartFactory;
    7. import org.jfree.chart.ChartUtilities;
    8. import org.jfree.chart.JFreeChart;
    9. import org.jfree.chart.axis.CategoryAxis;
    10. import org.jfree.chart.axis.CategoryLabelPositions;
    11. import org.jfree.chart.axis.NumberAxis;
    12. import org.jfree.chart.axis.NumberTickUnit;
    13. import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
    14. import org.jfree.chart.plot.CategoryPlot;
    15. import org.jfree.chart.plot.DatasetRenderingOrder;
    16. import org.jfree.chart.plot.PlotOrientation;
    17. import org.jfree.chart.renderer.category.LayeredBarRenderer;
    18. import org.jfree.chart.renderer.category.LineAndShapeRenderer;
    19. import org.jfree.data.category.DefaultCategoryDataset;
    20. import org.junit.Test;
    21. import org.springframework.boot.test.context.SpringBootTest;
    22. @SpringBootTest
    23. public class EchartsTest {
    24. public final static String filePathBarChart = "E:\\漏检率.png";
    25. /**
    26. * 绘制重叠柱状图和折线图组合
    27. * @Title: drawEcharts
    28. * @author Emily1_Zhang
    29. * @return: String
    30. */
    31. public String drawEcharts() {
    32. // 折線圖
    33. DefaultCategoryDataset lineDataset = new DefaultCategoryDataset();
    34. lineDataset.addValue(0, "漏检率", "F1 设备一部");
    35. lineDataset.addValue(0, "漏检率", "F1 设备二部");
    36. lineDataset.addValue(0, "漏检率", "F2 设备一部");
    37. lineDataset.addValue(0, "漏检率", "F2 设备二部");
    38. lineDataset.addValue(0.0364, "漏检率", "F3 AE一部-AW-一课");
    39. lineDataset.addValue(0.0123, "漏检率", "F3 AE一部-维护一课");
    40. lineDataset.addValue(0, "漏检率", "F3 ME一部-ME FA课");
    41. lineDataset.addValue(0.052, "漏检率", "F3 ME一部-ME一课");
    42. lineDataset.addValue(0, "漏检率", "F3 电子工程一部-AP课");
    43. lineDataset.addValue(0.0101, "漏检率", "F3 电子工程一部-RF课");
    44. lineDataset.addValue(0, "漏检率", "F4 AE一部-AE一课");
    45. lineDataset.addValue(0.0333, "漏检率", "F4 AE一部-AE一课");
    46. lineDataset.addValue(0, "漏检率", "F4 ME一部-ME FA课");
    47. lineDataset.addValue(0.0192, "漏检率", "F4 ME一部-ME二课");
    48. lineDataset.addValue(0, "漏检率", "F4 电子工程一部-AP课");
    49. lineDataset.addValue(0, "漏检率", "F4 电子工程一部-RF课");
    50. lineDataset.addValue(0.0217, "漏检率", "F5 AE二部-AF二课");
    51. lineDataset.addValue(0.0088, "漏检率", "F5 AE二部-维护二课");
    52. lineDataset.addValue(0, "漏检率", "F5 ME二部-ME三课");
    53. lineDataset.addValue(0, "漏检率", "F5 电子工程二部-AP课");
    54. lineDataset.addValue(0.0156, "漏检率", "F5 电子工程二部-RF课");
    55. lineDataset.addValue(0, "漏检率", "F6 AE三部-维护三课");
    56. lineDataset.addValue(0, "漏检率", "F6 ME二部-ME三课");
    57. // 柱狀圖
    58. DefaultCategoryDataset dataset = new DefaultCategoryDataset();
    59. dataset.addValue(0, "自检", "F1 设备一部");
    60. dataset.addValue(0, "自检", "F1 设备二部");
    61. dataset.addValue(0, "自检", "F2 设备一部");
    62. dataset.addValue(0, "自检", "F2 设备二部");
    63. dataset.addValue(50, "自检", "F3 AE一部-AW-一课");
    64. dataset.addValue(70, "自检", "F3 AE一部-维护一课");
    65. dataset.addValue(90, "自检", "F3 ME一部-ME FA课");
    66. dataset.addValue(195, "自检", "F3 ME一部-ME一课");
    67. dataset.addValue(100, "自检", "F3 电子工程一部-AP课");
    68. dataset.addValue(100, "自检", "F3 电子工程一部-RF课");
    69. dataset.addValue(70, "自检", "F4 AE一部-AE一课");
    70. dataset.addValue(50, "自检", "F4 AE一部-AE一课");
    71. dataset.addValue(100, "自检", "F4 ME一部-ME FA课");
    72. dataset.addValue(100, "自检", "F4 ME一部-ME二课");
    73. dataset.addValue(80, "自检", "F4 电子工程一部-AP课");
    74. dataset.addValue(100, "自检", "F4 电子工程一部-RF课");
    75. dataset.addValue(50, "自检", "F5 AE二部-AF二课");
    76. dataset.addValue(110, "自检", "F5 AE二部-维护二课");
    77. dataset.addValue(120, "自检", "F5 ME二部-ME三课");
    78. dataset.addValue(60, "自检", "F5 电子工程二部-AP课");
    79. dataset.addValue(60, "自检", "F5 电子工程二部-RF课");
    80. dataset.addValue(60, "自检", "F6 AE三部-维护三课");
    81. dataset.addValue(40, "自检", "F6 ME二部-ME三课");
    82. dataset.addValue(2, "复检", "F1 设备一部");
    83. dataset.addValue(10, "复检", "F1 设备二部");
    84. dataset.addValue(3, "复检", "F2 设备一部");
    85. dataset.addValue(6, "复检", "F2 设备二部");
    86. dataset.addValue(50, "复检", "F3 AE一部-AW-一课");
    87. dataset.addValue(80, "复检", "F3 AE一部-维护一课");
    88. dataset.addValue(105, "复检", "F3 ME一部-ME FA课");
    89. dataset.addValue(200, "复检", "F3 ME一部-ME一课");
    90. dataset.addValue(100, "复检", "F3 电子工程一部-AP课");
    91. dataset.addValue(101, "复检", "F3 电子工程一部-RF课");
    92. dataset.addValue(81, "复检", "F4 AE一部-AE一课");
    93. dataset.addValue(70, "复检", "F4 AE一部-AE一课");
    94. dataset.addValue(60, "复检", "F4 ME一部-ME FA课");
    95. dataset.addValue(105, "复检", "F4 ME一部-ME二课");
    96. dataset.addValue(115, "复检", "F4 电子工程一部-AP课");
    97. dataset.addValue(80, "复检", "F4 电子工程一部-RF课");
    98. dataset.addValue(89, "复检", "F5 AE二部-AF二课");
    99. dataset.addValue(50, "复检", "F5 AE二部-维护二课");
    100. dataset.addValue(100, "复检", "F5 ME二部-ME三课");
    101. dataset.addValue(110, "复检", "F5 电子工程二部-AP课");
    102. dataset.addValue(50, "复检", "F5 电子工程二部-RF课");
    103. dataset.addValue(40, "复检", "F6 AE三部-维护三课");
    104. dataset.addValue(40, "复检", "F6 ME二部-ME三课");
    105. // 生成柱狀圖
    106. JFreeChart chart = ChartFactory.createBarChart("BY 厂别漏检率汇总", "课别", // x轴的标签
    107. "总量", // y轴的标签
    108. dataset, // 图标显示的数据集合
    109. PlotOrientation.VERTICAL, true, true, false);
    110. chart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 10));
    111. // 处理图像上的乱码
    112. // 处理主标题的乱码
    113. chart.getTitle().setFont(new Font("黑体", Font.BOLD, 18));
    114. // 处理图表区域对象
    115. CategoryPlot categoryPlot = (CategoryPlot) chart.getPlot();
    116. // 获取X轴对象
    117. CategoryAxis categoryAxis = categoryPlot.getDomainAxis();
    118. // 获取第一条Y轴对象
    119. NumberAxis numberAxis0 = (NumberAxis) categoryPlot.getRangeAxis();
    120. // 第二条Y轴
    121. NumberAxis numberAxis = new NumberAxis("漏检率");
    122. // 数据显示格式是百分比
    123. DecimalFormat df = new DecimalFormat("0.000%");
    124. numberAxis.setNumberFormatOverride(df); // 数据轴数据标签的显示格式
    125. categoryPlot.setRangeAxis(1, numberAxis);
    126. categoryPlot.mapDatasetToRangeAxis(1, 1);
    127. // 处理X轴上的乱码
    128. categoryAxis.setTickLabelFont(new Font("黑体", Font.BOLD, 10));
    129. // 处理X轴外的乱码
    130. categoryAxis.setLabelFont(new Font("黑体", Font.BOLD, 10));
    131. // 处理Y轴上的乱码
    132. numberAxis0.setTickLabelFont(new Font("黑体", Font.BOLD, 10));
    133. numberAxis.setTickLabelFont(new Font("黑体", Font.BOLD, 10));
    134. // 处理Y轴外的乱码
    135. numberAxis0.setLabelFont(new Font("黑体", Font.BOLD, 10));
    136. numberAxis.setLabelFont(new Font("黑体", Font.BOLD, 10));
    137. // 自定义Y轴上显示的刻度,以30作为1格
    138. numberAxis0.setAutoTickUnitSelection(false);
    139. NumberTickUnit unit0 = new NumberTickUnit(30);
    140. numberAxis0.setTickUnit(unit0);
    141. //以1作为1格
    142. numberAxis.setAutoTickUnitSelection(false);
    143. NumberTickUnit unit = new NumberTickUnit(0.005);
    144. numberAxis.setTickUnit(unit);
    145. // 获取绘图区域对象
    146. // 重叠柱状图
    147. LayeredBarRenderer layeredBarRenderer = new LayeredBarRenderer();
    148. //设置第一个柱子的宽度
    149. layeredBarRenderer.setSeriesBarWidth(0, 1);
    150. //设置第二个柱子的宽度
    151. layeredBarRenderer.setSeriesBarWidth(1, 0.6);
    152. //设置柱子最小的高度
    153. layeredBarRenderer.setMinimumBarLength(0.1);
    154. //设置数字边框是否可见
    155. layeredBarRenderer.setDrawBarOutline(true);
    156. //设置第一个柱子颜色
    157. layeredBarRenderer.setSeriesPaint(0, new Color(82, 255, 66));
    158. //设置第二个柱子颜色
    159. layeredBarRenderer.setSeriesPaint(1, new Color(105, 90, 255));
    160. //设置每个课所包含的平行柱的之间距离
    161. layeredBarRenderer.setItemMargin(0.4);
    162. layeredBarRenderer.setBaseItemLabelFont(new Font("宋体", Font.BOLD, 10));
    163. categoryPlot.setRenderer(layeredBarRenderer);
    164. // 放折線圖
    165. categoryPlot.setDataset(1, lineDataset);
    166. // 設置折線
    167. LineAndShapeRenderer lineAndShapeRenderer = new LineAndShapeRenderer();
    168. lineAndShapeRenderer.setToolTipGenerator(new StandardCategoryToolTipGenerator());
    169. categoryPlot.setRenderer(1, lineAndShapeRenderer);
    170. // 柱狀圖和縱軸緊靠
    171. categoryAxis.setLowerMargin(0.0);
    172. categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
    173. categoryPlot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
    174. File file = new File(filePathBarChart);
    175. try {
    176. ChartUtilities.saveChartAsJPEG(file, chart, 800, 600);
    177. return filePathBarChart;
    178. } catch (Exception e) {
    179. e.printStackTrace();
    180. }
    181. return null;
    182. }
    183. @Test
    184. public void echart() {
    185. EchartsTest et=new EchartsTest();
    186. et.drawEcharts();
    187. }
    188. }