JavaFX 2 XYCharts和Java 7功能
我最喜歡的JavaFX 2功能之一是它在javafx.scene.chart包中提供的標(biāo)準(zhǔn)圖表。 該軟件包提供了幾種不同類型的現(xiàn)成圖表。 除了其中之一( PieChart )以外,所有其他都是“ 2軸圖”( XYChart的特定實(shí)現(xiàn))。 在本文中,我將介紹XYChart這些專業(yè)之間的共性。 在此過程中,我將介紹一些方便的Java 7功能。
接下來顯示javafx.scene.chart包中關(guān)鍵圖類型的UML類圖。 注意AreaChart , StackedAreaChart , BarChart , StackedBarChart , BubbleChart , LineChart和ScatterChart都擴(kuò)展了XYChart 。
正如上面的UML圖(使用JDeveloper生成)所示, PieChart直接擴(kuò)展Chart ,而所有其他圖表類型都擴(kuò)展XYChart 。 因?yàn)槌齈ieChart之外的所有其他圖表類型都擴(kuò)展了XYChart ,所以它們共享一些共同的功能。 例如,它們都是帶有水平('x')軸和垂直('y')軸的2軸圖表。 它們通常允許為所有XY圖表以相同的格式(數(shù)據(jù)結(jié)構(gòu))指定數(shù)據(jù)。 這篇文章的其余部分演示了能夠?qū)Υ蠖鄶?shù)XYChart使用相同的數(shù)據(jù)。
圖表的主要用途是顯示數(shù)據(jù),因此下一個(gè)代碼清單指示從Oracle數(shù)據(jù)庫中的“ hr ” 樣本架構(gòu)中檢索數(shù)據(jù)。 請(qǐng)注意,JDBC_URL,USERNAME,PASSWORD和AVG_SALARIES_PER_DEPARTMENT_QUERY是在JDBC連接和查詢中使用的常量字符串。
getAverageDepartmentsSalaries()
/*** Provide average salary per department name.* * @return Map of department names to average salary per department.*/ public Map<String, Double> getAverageDepartmentsSalaries() {final Map<String, Double> averageSalaryPerDepartment = new HashMap<>();try (final Connection connection = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD);final Statement statement = connection.createStatement();final ResultSet rs = statement.executeQuery(AVG_SALARIES_PER_DEPARTMENT_QUERY)){while (rs.next()){final String departmentName = rs.getString(COLUMN_DEPARTMENT_NAME);final Double salaryAverage = rs.getDouble(ALIAS_AVERAGE_SALARY);averageSalaryPerDepartment.put(departmentName, salaryAverage);}}catch (SQLException sqlEx){LOGGER.log(Level.SEVERE,'Unable to get average salaries per department - {0}', sqlEx.toString());}return averageSalaryPerDepartment; }上面的Java代碼段使用JDBC檢索數(shù)據(jù),以將部門名稱字符串Map為每個(gè)部門中雇員的平均工資。 此代碼中使用了幾個(gè)方便的Java 7功能。 一個(gè)小的功能是與局部變量averageSalaryPerDepartment的聲明一起使用的diamond運(yùn)算符的推斷通用參數(shù)化類型(第8行)。 這是語法糖的一小部分,但確實(shí)使代碼更簡(jiǎn)潔。
Java 7的一項(xiàng)更重要的功能是使用try-with-resources語句來處理Connection , Statement和ResultSet資源(第9-11行)。 與以前使用JDBC相比,即使面對(duì)異常,這也是處理這些資源打開和關(guān)閉的一種更好的方法。 try-with-resources語句上的Java Tutorials頁面廣告該語句“確保在語句末尾關(guān)閉每個(gè)資源”,并且確保每個(gè)資源都將被“關(guān)閉”,而不管try語句是正常完成還是突然完成。 該頁面還指出,與上述代碼一樣,在同一語句中指定了多個(gè)資源時(shí),“資源的close方法將按其創(chuàng)建的相反順序進(jìn)行調(diào)用。”
從數(shù)據(jù)庫檢索的數(shù)據(jù)可以放入適當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)中,以支持大多數(shù)XYCharts的使用。 這在下一個(gè)方法中顯示。
ChartMaker.createXyChartDataForAverageDepartmentSalary(地圖)
/*** Create XYChart Data representing average salary per department name.* * @param newAverageSalariesPerDepartment Map of department name (keys) to* average salary for each department (values).* @return XYChart Data representing average salary per department.*/ public static ObservableList<XYChart.Series<String, Double>> createXyChartDataForAverageDepartmentSalary(final Map<String, Double> newAverageSalariesPerDepartment) {final Series<String, Double> series = new Series<>();series.setName('Departments');for (final Map.Entry<String, Double> entry : newAverageSalariesPerDepartment.entrySet()){series.getData().add(new XYChart.Data<>(entry.getKey(), entry.getValue()));}final ObservableList<XYChart.Series<String, Double>> chartData =FXCollections.observableArrayList();chartData.add(series);return chartData; }剛剛顯示的方法將檢索到的數(shù)據(jù)放置在幾乎所有基于XYChart的圖表都可以使用的數(shù)據(jù)結(jié)構(gòu)中。 現(xiàn)在,將檢索到的數(shù)據(jù)打包到JavaFX可觀察的集合中,就可以輕松生成圖表。 下一個(gè)代碼片段顯示了用于生成多個(gè)基于XYChart的圖表(面積,條形圖,氣泡圖,折線圖和散點(diǎn)圖)的方法。 請(qǐng)注意它們都是多么相似,以及如何使用由相同方法提供的相同數(shù)據(jù)。 StackedBar和StackedArea圖表也可以使用類似的數(shù)據(jù),但此處未顯示,因?yàn)樗鼈儗?duì)于本示例中使用的單個(gè)數(shù)據(jù)系列沒有意義。
除BubbleChart和堆積圖表外的生成XYCharts的方法
private XYChart<String, Double> generateAreaChart(final Axis<String> xAxis, final Axis<Double> yAxis) {final AreaChart<String, Double> areaChart =new AreaChart<>(xAxis, yAxis,ChartMaker.createXyChartDataForAverageDepartmentSalary(this.databaseAccess.getAverageDepartmentsSalaries()));return areaChart; }private XYChart<String, Double> generateBarChart(final Axis<String> xAxis, final Axis<Double> yAxis) {final BarChart<String, Double> barChart =new BarChart<>(xAxis, yAxis,ChartMaker.createXyChartDataForAverageDepartmentSalary(this.databaseAccess.getAverageDepartmentsSalaries()));return barChart; }private XYChart<Number, Number> generateBubbleChart(final Axis<String> xAxis, final Axis<Double> yAxis) {final Axis<Number> deptIdXAxis = new NumberAxis();deptIdXAxis.setLabel('Department ID');final BubbleChart<Number, Number> bubbleChart =new BubbleChart(deptIdXAxis, yAxis,ChartMaker.createXyChartDataForAverageDepartmentSalaryById(this.databaseAccess.getAverageDepartmentsSalariesById()));return bubbleChart; }private XYChart<String, Double> generateLineChart(final Axis<String> xAxis, final Axis<Double> yAxis) {final LineChart<String, Double> lineChart =new LineChart<>(xAxis, yAxis,ChartMaker.createXyChartDataForAverageDepartmentSalary(this.databaseAccess.getAverageDepartmentsSalaries()));return lineChart; }private XYChart<String, Double> generateScatterChart(final Axis<String> xAxis, final Axis<Double> yAxis) {final ScatterChart<String, Double> scatterChart =new ScatterChart<>(xAxis, yAxis,ChartMaker.createXyChartDataForAverageDepartmentSalary(this.databaseAccess.getAverageDepartmentsSalaries()));return scatterChart; }這些方法是如此相似,以至于我實(shí)際上可以使用方法句柄(或更傳統(tǒng)的反射API)來反射性地調(diào)用適當(dāng)?shù)膱D表構(gòu)造函數(shù),而不是使用單獨(dú)的方法。 但是,我在2月的2013年RMOUG培訓(xùn)日演講中使用了這些功能,因此希望保留圖表專用的構(gòu)造函數(shù),以使它們對(duì)觀眾更清晰。
XYChart類型的常規(guī)處理的一個(gè)例外是BubbleChart的處理。 此圖表的x軸需要數(shù)字類型,因此上面提供的基于字符串(部門名稱)的x軸數(shù)據(jù)將不起作用。 另一種方法(此處未顯示)提供了一個(gè)查詢,該查詢按部門ID(長(zhǎng))而不是部門名稱返回平均工資。 接下來顯示了稍有不同的generateBubbleChart方法。
generateBubbleChart(Axis,Axis)
private XYChart<Number, Number> generateBubbleChart(final Axis<String> xAxis, final Axis<Double> yAxis){final Axis<Number> deptIdXAxis = new NumberAxis();deptIdXAxis.setLabel('Department ID');final BubbleChart<Number, Number> bubbleChart =new BubbleChart(deptIdXAxis, yAxis,ChartMaker.createXyChartDataForAverageDepartmentSalaryById(this.databaseAccess.getAverageDepartmentsSalariesById()));return bubbleChart;}可以編寫代碼來直接調(diào)用每種不同的圖表生成方法,但這為使用Java 7的方法句柄提供了一個(gè)很好的機(jī)會(huì)。 下一個(gè)代碼片段顯示了此操作。 該代碼不僅演示了方法句柄,而且還使用了Java 7的多捕獲異常處理機(jī)制(第77行)。
/*** Generate JavaFX XYChart-based chart.* * @param chartChoice Choice of chart to be generated.* @return JavaFX XYChart-based chart; may be null.* @throws IllegalArgumentException Thrown if the provided parameter is null.*/ private XYChart<String, Double> generateChart(final ChartTypes chartChoice) {XYChart<String, Double> chart = null;final Axis<String> xAxis = new CategoryAxis();xAxis.setLabel('Department Name');final Axis<? extends Number> yAxis = new NumberAxis();yAxis.setLabel('Average Salary');if (chartChoice == null){throw new IllegalArgumentException('Provided chart type was null; chart type must be specified.');}else if (!chartChoice.isXyChart()){LOGGER.log(Level.INFO,'Chart Choice {0} {1} an XYChart.',new Object[]{chartChoice.name(), chartChoice.isXyChart() ? 'IS' : 'is NOT'});}final MethodHandle methodHandle = buildAppropriateMethodHandle(chartChoice);try{chart =methodHandle != null? (XYChart<String, Double>) methodHandle.invokeExact(this, xAxis, yAxis): null;chart.setTitle('Average Department Salaries');}catch (WrongMethodTypeException wmtEx){LOGGER.log(Level.SEVERE,'Unable to invoke method because it is wrong type - {0}',wmtEx.toString());}catch (Throwable throwable){LOGGER.log(Level.SEVERE,'Underlying method threw a Throwable - {0}',throwable.toString());}return chart; }/*** Build a MethodHandle for calling the appropriate chart generation method* based on the provided ChartTypes choice of chart.* * @param chartChoice ChartTypes instance indicating which type of chart* is to be generated so that an appropriately named method can be invoked* for generation of that chart.* @return MethodHandle for invoking chart generation.*/ private MethodHandle buildAppropriateMethodHandle(final ChartTypes chartChoice) {MethodHandle methodHandle = null;final MethodType methodDescription =MethodType.methodType(XYChart.class, Axis.class, Axis.class);final String methodName = 'generate' + chartChoice.getChartTypeName() + 'Chart';try{methodHandle =MethodHandles.lookup().findVirtual(this.getClass(), methodName, methodDescription);}catch (NoSuchMethodException | IllegalAccessException exception){LOGGER.log(Level.SEVERE,'Unable to acquire MethodHandle to method {0} - {1}',new Object[]{methodName, exception.toString()});}return methodHandle; }隨后的一系列圖像顯示了由JavaFX渲染時(shí)這些XY圖表的顯示方式。
面積圖
條形圖
氣泡圖
折線圖
散點(diǎn)圖
如上所述,方法句柄可能已被用來進(jìn)一步減少代碼,因?yàn)橛糜谏擅總€(gè)XYChart各個(gè)方法不是絕對(duì)必要的,并且可以根據(jù)所需的圖表類型進(jìn)行反射式調(diào)用。 還值得強(qiáng)調(diào)的是,如果x軸數(shù)據(jù)是數(shù)字的,則所有XYChart類型(包括氣泡圖)的代碼都是相同的(并且可以被反射地調(diào)用)。
JavaFX使生成代表所提供數(shù)據(jù)的吸引人的圖表變得容易。 Java 7功能通過使代碼更簡(jiǎn)潔,更具表現(xiàn)力,并允許在適當(dāng)?shù)那闆r下輕松應(yīng)用反射,使此操作變得更加容易。
參考:來自JCG合作伙伴 Dustin Marx的JavaFX 2 XYCharts和Java 7功能,來自Inspired by Actual Events博客。
翻譯自: https://www.javacodegeeks.com/2013/01/javafx-2-xycharts-and-java-7-features.html
總結(jié)
以上是生活随笔為你收集整理的JavaFX 2 XYCharts和Java 7功能的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 联想乐phone手机(联想乐Phone)
- 下一篇: w7电脑屏保动态壁纸(w7设置动态壁纸)