У меня есть приложение погоды, которое я создаю, чтобы опробовать функции в JavaFX, но когда я звоню:
package controller.tab;
import application.CSVReader;
import controller.MainController;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.chart.*;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.stage.Window;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
public class Tab2Controller {
private MainController main;
private CSVReader CSVReader;
private int[] firstTimeCalled;
private ObservableList<XYChart.Series<String, Float>> firstLineChartData;
private ObservableList<XYChart.Series<String, Float>> secondLineChartData;
private ArrayList<XYChart.Data<String, Float>> list1;
private ArrayList<XYChart.Data<String, Float>> list2;
@FXML private LineChart<String, Float> firstLineChart;
@FXML private LineChart<String, Float> secondLineChart;
@FXML private ComboBox<String> comboSelect1;
@FXML private ComboBox<String> comboSelect2;
public void init(MainController mainController) {
main = mainController;
CSVReader = new CSVReader();
firstLineChartData = FXCollections.observableArrayList();
secondLineChartData = FXCollections.observableArrayList();
setChartsNotAnimated();
list1 = new ArrayList<>();
list2 = new ArrayList<>();
firstTimeCalled = new int[]{-1,-1};
}
public void initialiseCharts(String cityName) {
for (int i=0; i<4; i++) {
firstTimeCalled[i] = -1;
}
clearEverything(firstLineChart, firstLineChartData, list1, comboSelect1);
clearEverything(secondLineChart, secondLineChartData, list2, comboSelect2);
ArrayList<String> values = CSVReader.getYearlyStationStats(cityName);
if (!values.isEmpty()) {
for (String value : values) {
String[] coord = value.split(",");
list1.add(new XYChart.Data<>(coord[0], Float.parseFloat(coord[1])));
list2.add(new XYChart.Data<>(coord[0], Float.parseFloat(coord[2])));
}
firstLineChartData.add(new LineChart.Series<>(FXCollections.observableList(list1)));
secondLineChartData.add(new LineChart.Series<>(FXCollections.observableList(list2)));
firstLineChart.getData().setAll(firstLineChartData);
secondLineChart.getData().setAll(secondLineChartData);
ArrayList<String> cities = CSVReader.getAllYears(cityName);
for (String city : cities) {
comboSelect1.getItems().add(city);
comboSelect2.getItems().add(city);
}
comboSelect1.getItems().add("All years");
comboSelect2.getItems().add("All years");
firstLineChart.getYAxis().setLabel("Temperature (℃)");
firstLineChart.getXAxis().setLabel("Year");
secondLineChart.getYAxis().setLabel("Temperature (℃)");
secondLineChart.getXAxis().setLabel("Year");
firstLineChart.setTitle("Highest Max Mean Temperature vs. Years");
secondLineChart.setTitle("Lowest Min Mean Temperature vs. Years");
}
firstLineChart.setLegendVisible(false);
secondLineChart.setLegendVisible(false);
}
private void setChartsNotAnimated() {
firstLineChart.setAnimated(false);
secondLineChart.setAnimated(false);
}
private ArrayList<XYChart.Data<String, Float>> getSelectedData(String cityName, String year_selected, Integer indexOfData) {
ArrayList<String> selectedData = CSVReader.getAllData(cityName, year_selected);
list1 = new ArrayList<>();
for (String data : selectedData) {
String[] split_data = data.split(",");
list1.add(new XYChart.Data<>(changeToMonth(split_data[1]), Float.parseFloat(split_data[indexOfData])));
}
return list1;
}
private void fillChart(String cityName, int index, String year_selected, ComboBox<String> newBox, XYChart<String, Float> chart, ObservableList<XYChart.Series<String, Float>> list){
if (cityName != null && !newBox.getSelectionModel().isEmpty()) {
if (year_selected.compareTo("All years")==0){
for (String year : CSVReader.getAllYears(cityName)){
if(!checkChartContains(year, list)) {
list1 = getSelectedData(cityName, year, index);
list.add(new LineChart.Series<>(year, FXCollections.observableList(list1)));
}
}
} else {
list1 = getSelectedData(cityName, year_selected, index);
Window current = chart.getScene().getWindow();
checkValidity(current, year_selected, FXCollections.observableList(list1), list);
}
chart.getXAxis().setLabel("Month");
if (index == 2) {
chart.setTitle("Highest Max Mean Temperature vs. Months");
}
if (index == 3) {
chart.setTitle("Lowest Min Mean Temperature vs. Months");
}
if (index == 4) {
chart.setTitle("Total Frost Days vs. Months");
}
if (index == 5) {
chart.setTitle("Total Rainfall vs. Months");
}
}
chart.getData().setAll(list);
}
@FXML
private void addDataToChart(ActionEvent event) {
String cityName = main.getCityName();
Button btn = (Button) event.getSource();
String year_selected;
if (btn.getId().compareTo("btnAdd1")==0) {
year_selected = comboSelect1.getSelectionModel().getSelectedItem();
clearDataOnly(0);
fillChart(cityName,2, year_selected, comboSelect1, firstLineChart, firstLineChartData);
}
if (btn.getId().compareTo("btnAdd2")==0) {
year_selected = comboSelect2.getSelectionModel().getSelectedItem();
clearDataOnly(1);
fillChart(cityName,3, year_selected, comboSelect2, secondLineChart, secondLineChartData);
}
}
@FXML private void revertCharts() {
String cityName = main.getCityName();
initialiseCharts(cityName);
}
private void clearAxis(XYChart<String, Float> chart) {
chart.getYAxis().setLabel("");
chart.getXAxis().setLabel("");
chart.setTitle("");
}
private void clearEverything(XYChart<String,Float> chart,
ObservableList<XYChart.Series<String, Float>> chartData,
ArrayList<XYChart.Data<String, Float>> series_list,
ComboBox<String> comboBox) {
chart.getData().clear();
chartData.clear();
series_list.clear();
comboBox.getItems().clear();
}
@FXML
private void clearChartOnly(ActionEvent event) {
Button btn = (Button) event.getSource();
if (btn.getId().compareTo("btnClear1")==0) {
firstLineChartData.clear();
firstLineChart.getData().clear();
clearAxis(firstLineChart);
}
if (btn.getId().compareTo("btnClear2")==0) {
secondLineChartData.clear();
secondLineChart.getData().clear();
clearAxis(secondLineChart);
}
}
private void clearDataOnly(Integer number) {
if ((firstTimeCalled[number] == -1) && (number == 0)) {
firstLineChart.getData().clear();
firstLineChartData.clear();
firstTimeCalled[number] = 1;
firstLineChart.setLegendVisible(true);
}
if ((firstTimeCalled[number] == -1) && (number == 1)) {
secondLineChart.getData().clear();
secondLineChartData.clear();
firstTimeCalled[number] = 1;
secondLineChart.setLegendVisible(true);
}
}
private String changeToMonth(String number) {
DateFormatSymbols dfs = new DateFormatSymbols();
String[] months = dfs.getMonths();
return months[Integer.parseInt(number)-1];
}
private static void showAlert(Window owner, String title, String message) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(message);
alert.initOwner(owner);
alert.show();
}
private boolean checkChartContains(String year_selected, ObservableList<XYChart.Series<String, Float>> chartToAddTo) {
for (LineChart.Series<String, Float> series1 : chartToAddTo) {
if(series1.getName().compareTo(year_selected)==0){
return true;
}
}
return false;
}
private void checkValidity(Window current, String year_selected, ObservableList<XYChart.Data<String,Float>> observableFloatList, ObservableList<XYChart.Series<String, Float>> chartToAddTo) {
boolean alreadyContains = checkChartContains(year_selected, chartToAddTo);
if (alreadyContains && chartToAddTo.size()>=3) {
showAlert(current, "Unnecessary Extra Data", "The graph already contains 3 or more sets of data, you cannot add more.");
} else if (chartToAddTo.size()>=3) {
showAlert(current, "Unnecessary Extra Data", "The graph already contains 3 or more sets of data, you cannot add more.");
} else if (alreadyContains) {
showAlert(current, "Already Exists", "The graph already contains this data, it cannot be added again.");
}
if (!alreadyContains && chartToAddTo.size()<3) {
chartToAddTo.add(new LineChart.Series<>(year_selected, observableFloatList));
}
}
} я получаю следующее, но только на secondLineChart
, первая диаграмма не не делай этого, есть ли ошибка, о которой я должен знать? Я добавляю строку данных, и когда я ее очищаю, я получаю следующую проблему, мой код очень длинный, поэтому я выветрил его (простите за каламбур), чтобы сделать его немного легче для чтения, вызовы для очистки находятся в обычно функция и переменные secondLineChartData
и list2
инициализируются. Если вам нужно больше кода, чем я, я с радостью добавлю его, мне просто интересно, будет ли этот код более простым для исправления.
Заранее спасибо.