如何使用 ObservableLists 在 Javafx 中创建条形图或折线图
How to create a BarChart or a LineChart in Javafx Using ObservableLists
我正在尝试使用 Java 从 sql 数据库中保存的数据生成统计图(条形图和折线图)。
预计数据会不时更改。
我尝试使用 ObservableLists,但收到错误消息。
以下是我到目前为止所尝试过的;
注意:这位于 DatabaseHandler class
public ObservableList<BarChart.Data> getItemGraphStatistics(){
ObservableList<BarChart.Data> data = FXCollections.observableArrayList();
String sql = "SELECT itemID, COUNT(*) FROM (SELECT itemID FROM SALES UNION ALL SELECT itemID FROM STOCK) t GROUP BY itemID";
System.out.println(sql );
ResultSet rs = handler.execQuery(sql);
try{
while(rs.next()){
String item= rs.getString("itemID");
int count = rs.getInt(2);
data.add(new BarChart.Data(item+ "(" + count + ")", count));
}
} catch (SQLException ex) {
Logger.getLogger(DatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return data;
}
在 运行 上面得到
java.lang.ClassCastException: javafx.scene.chart.XYChart$Data cannot be cast to javafx.scene.chart.XYChart$Series
当我尝试将 BarChart.Data 更改为 BarChart.Series 时,我无法将 int 转换为 observableList 错误消息。
下面是上面的试用例子;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXRadioButton;
import com.jfoenix.controls.JFXTextField;
import java.net.URL;
import java.util.Calendar;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import sales.manager.database.DatabaseHandler;
/**
* FXML Controller class
*
* @author Garande
*/
public class PerformanceAnalyzerController implements Initializable {
@FXML
private AnchorPane analysisHandler;
@FXML
private AnchorPane graphHandler;
@FXML
private PieChart piechart;
@FXML
private BarChart<?, ?> barchart;
@FXML
private LineChart<?, ?> linechart;
@FXML
private NumberAxis yBarGraph;
@FXML
private CategoryAxis xBarGraph;
@FXML
private NumberAxis yLineGraph;
@FXML
private CategoryAxis xLineGraph;
DatabaseHandler handler = DatabaseHandler.getInstance();
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
}
@FXML
private void performAnalysisOperation(ActionEvent event) {
//Performing analysis operation
barchart.setData(handler.getItemGraphStatistics());
graphHandler.getChildren().add(barchart);
}
}
XYChart
的 data
属性 持有 ObservableList<XYChart.Series>
。每个 XYChart.Series
也 有一个 data
属性,但它持有一个 ObservableList<XYChart.Data>
。问题是您的方法 returns 一个 ObservableList<XYChart.Data>
然后您尝试在 XYChart.data
上设置——类型不匹配。我不确定您是如何获得 ClassCastException
,因为您的代码甚至不应该编译。
您需要将数据列表包装成一个系列,然后将该系列添加到图表中。你也应该avoid using raw types。 Series
和 Data
都有类型参数,但您没有指定它们。根据您构建 Data
的方式,您的代码应该类似于(为简洁起见省略了一些代码):
public class PerformanceAnalyzerController {
@FXML private BarChart<String, Number> barChart;
@FXML
private void performAnalysisOperation(ActionEvent event) {
//Performing analysis operation
ObservableList<XYChart.Data<String, Number>> data = handler.getItemsGraphicsStatisitics();
XYChart.Series<String, Number> series = new XYChart.Series<>("Series Name", data);
barchart.getData().setAll(series);
graphHandler.getChildren().add(barchart);
}
}
并且:
// Use generic types
public ObservableList<XYChart.Data<String, Number>> getItemGraphStatistics(){
ObservableList<XYChart.Data<String, Number>> data = FXCollections.observableArrayList();
String sql = "SELECT itemID, COUNT(*) FROM (SELECT itemID FROM SALES UNION ALL SELECT itemID FROM STOCK) t GROUP BY itemID";
System.out.println(sql );
ResultSet rs = handler.execQuery(sql);
try{
while(rs.next()){
String item= rs.getString("itemID");
int count = rs.getInt(2);
// add diamond operator "<>"
data.add(new XYChart.Data<>(item+ "(" + count + ")", count));
}
} catch (SQLException ex) {
Logger.getLogger(DatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return data;
}
注意:我用 XYChart.Data
替换了 BarChart.Data
的用法,但我认为在这种情况下它不重要。
我正在尝试使用 Java 从 sql 数据库中保存的数据生成统计图(条形图和折线图)。 预计数据会不时更改。
我尝试使用 ObservableLists,但收到错误消息。
以下是我到目前为止所尝试过的; 注意:这位于 DatabaseHandler class
public ObservableList<BarChart.Data> getItemGraphStatistics(){
ObservableList<BarChart.Data> data = FXCollections.observableArrayList();
String sql = "SELECT itemID, COUNT(*) FROM (SELECT itemID FROM SALES UNION ALL SELECT itemID FROM STOCK) t GROUP BY itemID";
System.out.println(sql );
ResultSet rs = handler.execQuery(sql);
try{
while(rs.next()){
String item= rs.getString("itemID");
int count = rs.getInt(2);
data.add(new BarChart.Data(item+ "(" + count + ")", count));
}
} catch (SQLException ex) {
Logger.getLogger(DatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return data;
}
在 运行 上面得到
java.lang.ClassCastException: javafx.scene.chart.XYChart$Data cannot be cast to javafx.scene.chart.XYChart$Series
当我尝试将 BarChart.Data 更改为 BarChart.Series 时,我无法将 int 转换为 observableList 错误消息。
下面是上面的试用例子;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXRadioButton;
import com.jfoenix.controls.JFXTextField;
import java.net.URL;
import java.util.Calendar;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import sales.manager.database.DatabaseHandler;
/**
* FXML Controller class
*
* @author Garande
*/
public class PerformanceAnalyzerController implements Initializable {
@FXML
private AnchorPane analysisHandler;
@FXML
private AnchorPane graphHandler;
@FXML
private PieChart piechart;
@FXML
private BarChart<?, ?> barchart;
@FXML
private LineChart<?, ?> linechart;
@FXML
private NumberAxis yBarGraph;
@FXML
private CategoryAxis xBarGraph;
@FXML
private NumberAxis yLineGraph;
@FXML
private CategoryAxis xLineGraph;
DatabaseHandler handler = DatabaseHandler.getInstance();
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
}
@FXML
private void performAnalysisOperation(ActionEvent event) {
//Performing analysis operation
barchart.setData(handler.getItemGraphStatistics());
graphHandler.getChildren().add(barchart);
}
}
XYChart
的 data
属性 持有 ObservableList<XYChart.Series>
。每个 XYChart.Series
也 有一个 data
属性,但它持有一个 ObservableList<XYChart.Data>
。问题是您的方法 returns 一个 ObservableList<XYChart.Data>
然后您尝试在 XYChart.data
上设置——类型不匹配。我不确定您是如何获得 ClassCastException
,因为您的代码甚至不应该编译。
您需要将数据列表包装成一个系列,然后将该系列添加到图表中。你也应该avoid using raw types。 Series
和 Data
都有类型参数,但您没有指定它们。根据您构建 Data
的方式,您的代码应该类似于(为简洁起见省略了一些代码):
public class PerformanceAnalyzerController {
@FXML private BarChart<String, Number> barChart;
@FXML
private void performAnalysisOperation(ActionEvent event) {
//Performing analysis operation
ObservableList<XYChart.Data<String, Number>> data = handler.getItemsGraphicsStatisitics();
XYChart.Series<String, Number> series = new XYChart.Series<>("Series Name", data);
barchart.getData().setAll(series);
graphHandler.getChildren().add(barchart);
}
}
并且:
// Use generic types
public ObservableList<XYChart.Data<String, Number>> getItemGraphStatistics(){
ObservableList<XYChart.Data<String, Number>> data = FXCollections.observableArrayList();
String sql = "SELECT itemID, COUNT(*) FROM (SELECT itemID FROM SALES UNION ALL SELECT itemID FROM STOCK) t GROUP BY itemID";
System.out.println(sql );
ResultSet rs = handler.execQuery(sql);
try{
while(rs.next()){
String item= rs.getString("itemID");
int count = rs.getInt(2);
// add diamond operator "<>"
data.add(new XYChart.Data<>(item+ "(" + count + ")", count));
}
} catch (SQLException ex) {
Logger.getLogger(DatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return data;
}
注意:我用 XYChart.Data
替换了 BarChart.Data
的用法,但我认为在这种情况下它不重要。