JavaFX to create bar graph

JavaFX to create bar graph

Coursework: Bar Charts

In this coursework you must design, implement, test and document an application in Java to display bar charts. Your application must feature a graphical user interface.
You must write classes for a NetBeansproject that uses JavaFXto create a graphical user interface. You must design, implement, test and document a program in Java that fulfils all the functional requirements (FR) and all the non‐functional requirements (NFR) indicated below.

You must document all of this in a report. The report must include neatly formatted copies of your Java source and evidence of your testing, including screen images from your running program.
In your report you must reflect honestly on the degree of success you have achieved.
The marking will be done on the basis of your report alone. It must not be necessary for the marker to investigate your program files.

Functional Requirements

  1. FR1  None of the panes in your interface should be resizable.
  2. FR2  The program must create a pane that is functionally equivalent to (but not necessarily identical to) that of Figure 1. (See section headed Figures)

The following functional requirements pertain to the option: Generate Bar chart.

  1. FR3  The program must allow the user to input text to the fields labelled Title, X‐Axis label and Y‐Axis label. This is illustrated in Figure 2.
  2. FR4  The values input to the text fields labelled Title, X‐Axis label and Y‐Axis label must be read by the program and used to annotate the charts it creates.
  3. FR5  The program must allow the user to click on the check boxes headed Enabled in the figures. In Figure 1 the topmost of these is already enabled.
  4. FR6  Clicking on a check box must make the corresponding text fields alongside it, headed Item Name and Value, become available for user input.
  5. FR7  The program must allow the user to input text to the fields labelled Item Name and Value. See Figure 3.
  6. FR8  The program must read the values input to the text fields labelled Item Name and Value. See Figure 3.
  7. FR9  If the user now clicks on the button labelled Generate Bar Chart, the program must use the values that have been entered into the text fields labelled Item Name and Value to create a bar chart. The axes of the chart must be scaled suitably to make the chart fit the pane. See Figure 4.
    There is no particular significance to the colours used in this or any other of the charts.

The following functional requirements pertain to the option: Generate From CSV.

  1. FR10  If the user clicks on the button labelled Generate From CSV (without needing to enable any check boxes or input any text) the program must present the user with a means of selecting an existing file in comma‐separated‐value format (csv) and must then create a bar chart from the values held in the file. See Figure 5.
  2. FR11  If the file cannot be found, or is not in the correct format, the program must indicate an error by some means that is visible to the user. As an example, Figure 6 shows how this can be achieved for a variant of the file csv that has “xxx” in the cell for Tesco’s market share, where there should be a number.

Non‐functional Requirements

  1. NFR1  The program must be written in Java.
  2. NFR2  The graphical user interface must be created using JavaFX.
  3. NFR3  The code produced must respect standard Java naming conventions for classes, variables, and methods and must also respect the Java programming guidelines for this module. See the Java Conventions and Programming Guidelines document on this module’s Moodle site.
  4. NFR4  The code must make appropriate use of object‐oriented programming concepts.
  5. NFR5  The code must make appropriate use of exception‐handling features.
  6. NFR6  Your code must be easy to understand, and no more complicated than is necessary. See Java Conventions and Programming Guidelines.
  7. NFR7  Your code must be economical and not unduly repetitive. You must make appropriate use of loops and methods to avoid unnecessary repetition of code.
  8. NFR8  Your program must use anonymous classes or lambda expressions for handling button‐press events.

Data

supermarketmarketshare

Supermarket Market Share,Share (%),Supermarket

Tesco,28

Sainsbury’s,17

Asda,16

Morrisons,12

Co-op,7

Aldi,6.5

Waitrose,5.5

Lidl,5

Iceland,3 

Solution 

BarChartItem.java 

packagebarchartsfx;

classBarChartItem

{

private String Name;

private Double Value;

BarChartItem(String name, Double value)

{

Name = name;

Value = value;

}

String getName()

{

return Name;

}

Double getValue()

{

return Value;

}

} 

BarCharts.java 

/*

* To change this license header, choose License Headers in Project Properties.

* To change this template file, choose Tools | Templates

* and open the template in the editor.

*/

packagebarchartsfx;

importjavafx.application.Application;

importjavafx.fxml.FXMLLoader;

importjavafx.scene.Parent;

importjavafx.scene.Scene;

importjavafx.stage.Stage;

/**

*

* @author Oleg

*/

public class BarCharts extends Application {

@Override

public void start(Stage stage) throws Exception {

Parent root = FXMLLoader.load(getClass().getResource(“FXMLDocument.fxml”));

Scene scene = new Scene(root);

stage.setTitle(“Bar Chart Generator”);

stage.setScene(scene);

stage.show();

}

/**

* @paramargs the command line arguments

*/

public static void main(String[] args) {

launch(args);

}

} 

BarChartsFX.java 

/*

* To change this license header, choose License Headers in Project Properties.

* To change this template file, choose Tools | Templates

* and open the template in the editor.

*/

packagebarchartsfx;

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileNotFoundException;

importjava.io.FileReader;

importjava.io.IOException;

importjava.util.ArrayList;

importjava.util.logging.Level;

importjava.util.logging.Logger;

importjavafx.application.Application;

importjavafx.event.ActionEvent;

importjavafx.event.EventHandler;

importjavafx.geometry.Insets;

importjavafx.geometry.Pos;

importjavafx.scene.Scene;

importjavafx.scene.control.Button;

importjavafx.scene.control.CheckBox;

importjavafx.scene.control.Label;

importjavafx.scene.control.TextField;

importjavafx.scene.layout.AnchorPane;

importjavafx.scene.layout.GridPane;

importjavafx.stage.FileChooser;

importjavafx.stage.FileChooser.ExtensionFilter;

importjavafx.stage.Stage;

public class BarChartsFX extends Application {

privateTextFieldtextFieldTitle;

privateTextFieldtextFieldXAxis;

privateTextFieldtextFieldYAxis;

privateArrayList<TextField>textFieldsName;

privateArrayList<TextField>textFieldsValue;

privateArrayList<CheckBox>checkboxesEnabled;

private Label     labelErrorPlaceHolder;

BarChartToolbarChartTool;

@Override

public void start(Stage primaryStage) {

Label labelTitle = new Label();

labelTitle.setLayoutX(14.0);

labelTitle.setLayoutY(14.0);

labelTitle.setText(“Title:”);

textFieldTitle = new TextField();

textFieldTitle.setLayoutX(97.0);

textFieldTitle.setLayoutY(10.0);

textFieldTitle.setPromptText(“Title”);

Label labelXAxis = new Label();

labelXAxis.setLayoutX(14.0);

labelXAxis.setLayoutY(44.0);

labelXAxis.setText(“X-Axis Label:”);

Label labelYAxis = new Label();

labelYAxis.setLayoutX(14.0);

labelYAxis.setLayoutY(72.0);

labelYAxis.setText(“Y-Axis Label:”);

textFieldXAxis = new TextField();

textFieldXAxis.setLayoutX(97.0);

textFieldXAxis.setLayoutY(40.0);

textFieldXAxis.setPromptText(“Description of Items”);

textFieldYAxis = new TextField();

textFieldYAxis.setLayoutX(97.0);

textFieldYAxis.setLayoutY(68.0);

textFieldYAxis.setPromptText(“Description of Item Value”);

Button buttonGenerate = new Button();

buttonGenerate.setLayoutX(9.0);

buttonGenerate.setLayoutY(108.0);

buttonGenerate.setPrefWidth(238);

buttonGenerate.setPrefHeight(25);

buttonGenerate.setText(“Generate Bar Chart”);

buttonGenerate.setOnAction(e ->handleGenerateButtonClick());

Button buttonGenerateCSV = new Button();

buttonGenerateCSV.setLayoutX(9.0);

buttonGenerateCSV.setLayoutY(147.0);

buttonGenerateCSV.setPrefWidth(238);

buttonGenerateCSV.setPrefHeight(25);

buttonGenerateCSV.setText(“Generate From CSV”);

buttonGenerateCSV.setOnAction(e ->handleCSVButtonClick());

labelErrorPlaceHolder = new Label();

labelErrorPlaceHolder.setAlignment(Pos.TOP_LEFT);

labelErrorPlaceHolder.setLayoutX(9.0);

labelErrorPlaceHolder.setLayoutY(185.0);

labelErrorPlaceHolder.setPrefWidth(238.0);

labelErrorPlaceHolder.setPrefHeight(152.0);

AnchorPane root = new AnchorPane();

root.getChildren().add(labelTitle);

root.getChildren().add(textFieldTitle);

root.getChildren().add(labelXAxis);

root.getChildren().add(labelYAxis);

root.getChildren().add(textFieldXAxis);

root.getChildren().add(textFieldYAxis);

root.getChildren().add(buttonGenerate);

root.getChildren().add(buttonGenerateCSV);

root.getChildren().add(labelErrorPlaceHolder);

root.getChildren().add(createItemsPane());

Scene scene = new Scene(root, 494, 343);

primaryStage.setTitle(“Bar Chart Generator”);

primaryStage.setScene(scene);

primaryStage.show();

}

privateGridPanecreateItemsPane()

{

textFieldsName = new ArrayList<>();

textFieldsValue = new ArrayList<>();

checkboxesEnabled = new ArrayList<>();

GridPanegridPane = new GridPane();

gridPane.setVgap(12);

gridPane.setHgap(10);

gridPane.setLayoutX(270);

gridPane.setLayoutY(14);

gridPane.add(new Label(“Item Name”), 0, 0);

gridPane.add(new Label(“Value”), 1, 0);

gridPane.add(new Label(“Enabled”), 2, 0);

for (int i = 0; i < 10; i++)

{

TextFieldtextFieldName = new TextField();

textFieldName.setDisable(true);

textFieldName.setPrefWidth(80.0);

textFieldName.setPrefHeight(25.0);

textFieldName.setPromptText(“Item Name”);

TextFieldtextFieldValue = new TextField();

textFieldValue.setDisable(true);

textFieldValue.setPrefWidth(80.0);

textFieldValue.setPrefHeight(25.0);

textFieldValue.setPromptText(“e.g. 50”);

CheckBoxcheckBoxEnabled = new CheckBox();

checkBoxEnabled.setMnemonicParsing(false);

checkBoxEnabled.setOnAction((ActionEvent event) -> {

if (checkBoxEnabled.isSelected())

{

textFieldValue.setDisable(false);

textFieldName.setDisable(false);

}

else

{

textFieldValue.setDisable(true);

textFieldName.setDisable(true);

}

});

gridPane.add(textFieldName, 0, i + 1);

gridPane.add(textFieldValue, 1, i + 1);

gridPane.add(checkBoxEnabled, 2, i + 1);

textFieldsName.add(textFieldName);

textFieldsValue.add(textFieldValue);

checkboxesEnabled.add(checkBoxEnabled);

}

returngridPane;

}

private void handleGenerateButtonClick()

{

barChartTool = new BarChartToolImpl();

barChartTool.setName(textFieldTitle.getText());

barChartTool.setXAxisName(textFieldXAxis.getText());

barChartTool.setYAxisName(textFieldYAxis.getText());

for (int i = 0; i <checkboxesEnabled.size(); i++)

{

try

{

Double value = Double.parseDouble(

textFieldsValue.get(i).getText());

String name = textFieldsName.get(i).getText();

barChartTool.addItem(name, value);

}

catch (NumberFormatException e)

{}

}

barChartTool.show();

}

private void handleCSVButtonClick() {

FileChooserfileChooser = new FileChooser();

fileChooser.setTitle(“Open CSV File”);

fileChooser.setInitialDirectory(new java.io.File( “.” ));

fileChooser.getExtensionFilters().addAll(

newExtensionFilter(“CSV Files”, “*.csv”));

File selectedFile = fileChooser.showOpenDialog(null);

BarChartTooltempBarChart = new BarChartToolImpl();

booleandataIsCorrect = true;

if (selectedFile != null)

{

BufferedReaderbr = null;

String line = “”;

String cvsSplitBy = “,”;

try {

br = new BufferedReader(new FileReader(

selectedFile.getAbsolutePath()));

line = br.readLine();

String[] headers = line.split(cvsSplitBy);

if (headers.length< 3)

{

dataIsCorrect = false;

}

if (dataIsCorrect)

{

tempBarChart.setName(headers[0]);

tempBarChart.setYAxisName(headers[1]);

tempBarChart.setXAxisName(headers[2]);

}

while ((line = br.readLine()) != null &&dataIsCorrect)

{

// use comma as separator

String[] dataPair = line.split(cvsSplitBy);

if (dataPair.length != 2)

{

dataIsCorrect = false;

break;

}

Double value;

try

{

value = Double.parseDouble(dataPair[1]);

tempBarChart.addItem(dataPair[0], value);

}

catch (NumberFormatException e)

{

dataIsCorrect = false;

}

}

}

catch (FileNotFoundException e)

{

dataIsCorrect = false;

e.printStackTrace();

}

catch (IOException e)

{

dataIsCorrect = false;

e.printStackTrace();

}

finally

{

if (br != null)

{

try

{

br.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

if (dataIsCorrect)

{

barChartTool = tempBarChart;

barChartTool.show();

}

else

{

labelErrorPlaceHolder.setText(“The file structure is not correct.”);

}

}

}

/**

* @paramargs the command line arguments

*/

public static void main(String[] args) {

launch(args);

}

} 

BarChartTool.java

packagebarchartsfx;

public interface BarChartTool

{

voidsetName(String name);

voidsetXAxisName(String name);

voidsetYAxisName(String name);

voidaddItem(String name, Double value);

void show();

} 

BarChartToolImpl.java 

packagebarchartsfx;

importjava.util.ArrayList;

importjavafx.scene.Scene;

importjavafx.scene.chart.BarChart;

importjavafx.scene.chart.CategoryAxis;

importjavafx.scene.chart.NumberAxis;

importjavafx.scene.chart.XYChart;

importjavafx.stage.Stage;

public class BarChartToolImpl implements BarChartTool

{

public String ChartName;

public String XAxisName;

public String YAxisName;

privateArrayList<BarChartItem>DataItems = new ArrayList<BarChartItem>();

private Stage stage;

public void setName(String name)

{

ChartName = name;

}

public void setXAxisName(String name)

{

XAxisName = name;

}

public void setYAxisName(String name)

{

YAxisName = name;

}

public void addItem(String name, Double value)

{

DataItems.add(new BarChartItem(name, value));

}

public void show()

{

finalCategoryAxisxAxis = new CategoryAxis();

finalNumberAxisyAxis = new NumberAxis();

finalBarChart<String, Number>bc =

newBarChart<String, Number>(xAxis,yAxis);

bc.setTitle(getName());

xAxis.setLabel(getXAxisName());

yAxis.setLabel(getYAxisName());

for (BarChartItembarChartItem : DataItems)

{

XYChart.Series series = new XYChart.Series();

series.getData().add(new XYChart.Data(

barChartItem.getName(),  barChartItem.getValue()));

bc.getData().add(series);

}

Scene scene  = new Scene(bc,800,600);

stage = new Stage();

stage.setTitle(getName());

stage.setScene(scene);

stage.show();

}

/**

* @return the ChartName

*/

public String getName() {

returnChartName;

}

/**

* @return the XAxisName

*/

public String getXAxisName() {

returnXAxisName;

}

/**

* @return the YAxisName

*/

public String getYAxisName() {

returnYAxisName;

}

publicintgetItemsCount()

{

returnDataItems.size();

}

}