Skip to content
Snippets Groups Projects
Commit 3d48f7c3 authored by Hugo Debuyser's avatar Hugo Debuyser
Browse files

Ajout de javadoc pour toutes les classes

parent 4eafa050
Branches
Tags
No related merge requests found
Showing
with 464 additions and 239 deletions
......@@ -30,9 +30,8 @@ public class DataStageController {
/**
* Ouvrir les paramètres des axes de la vue
* @throws IOException
*/
public void openAxesSetting()throws IOException {
public void openAxesSetting(){
AxesSettingsView axesSettingsView = new AxesSettingsView(ClassificationModel.getClassificationModel(), stage, dataStageView);
axesSettingsView.show();
}
......
......@@ -43,7 +43,7 @@ public class LoadDataController {
/**
* Valide le fichier sélectionné au préalable
*/
public void validate() throws IOException {
public void validate(){
if (file == null || file.isDirectory() || !file.exists()) {
Alert alert = new Alert(Alert.AlertType.ERROR);
......
......@@ -10,15 +10,11 @@ import javafx.stage.Stage;
import java.io.IOException;
public class MainStageController {
@FXML
Stage stage;
@FXML
Button classifyData;
......@@ -28,36 +24,38 @@ public class MainStageController {
@FXML
Label AxesSelected;
private MainStageView mainStageView;
/**
* Ouvre l'interface de chargement des données.
* Permet à l'utilisateur de sélectionner des données à charger pour la classification.
*/
public void openLoadData() throws IOException {
public void openLoadData() {
LoadDataView loadDataView = new LoadDataView(ClassificationModel.getClassificationModel(), stage);
loadDataView.show();
}
/**
* Ouvre l'interface d'une nouvelle vue.
* Affiche une nouvelle fenêtre pour visualiser les données après classification.
*/
public void openDataView() throws IOException {
public void openDataView() {
DataStageView dataStageView = new DataStageView(ClassificationModel.getClassificationModel());
dataStageView.show();
}
/**
* Ouvre l'interface de la configuration des axes.
* Permet à l'utilisateur de définir les axes du graphique.
*/
public void openAxesSetting()throws IOException {
public void openAxesSetting() {
AxesSettingsView axesSettingsView = new AxesSettingsView(ClassificationModel.getClassificationModel(), stage, mainStageView);
axesSettingsView.show();
}
/**
* Associe la mainStageView associer à la classe
* @param mainStageView
* Associe la mainStageView à la classe.
* @param mainStageView Instance de MainStageView à associer.
*/
public void setMainStageView(MainStageView mainStageView) {
this.mainStageView = mainStageView;
......@@ -65,14 +63,16 @@ public class MainStageController {
/**
* Ouvre l'interface d'ajout de donnée.
* Permet à l'utilisateur d'ajouter de nouvelles données à classifier.
*/
public void openAddData() throws IOException {
public void openAddData() {
AddDataView addDataView = new AddDataView(ClassificationModel.getClassificationModel(), stage, mainStageView);
addDataView.show();
}
/**
* Appelle de la méthode de la classe ClassificationModel afin de classifier les nouvelles données
* Appelle la méthode de la classe ClassificationModel afin de classifier les nouvelles données.
* Désactive le bouton de classification après l'appel de la méthode.
*/
public void classifyDatas() {
ClassificationModel.getClassificationModel().classifierDonnees();
......@@ -80,24 +80,24 @@ public class MainStageController {
}
/**
* Renvoie la grille associé à la classe
* @return grille de la classe
* Renvoie la grille associée à la classe.
* @return grille de type ScatterChart utilisée pour la visualisation des données.
*/
public ScatterChart getScatterChart() {
return this.scatterChart;
}
/**
* Attribut une valeur à l'axe de la grille
* @param texte Valeur de l'axe
* Attribue une valeur à l'axe de la grille.
* @param texte Valeur de l'axe à afficher sur l'interface.
*/
public void setAxesSelected(String texte) {
this.AxesSelected.setText(texte);
}
/**
* Renvoie le bouton de classification de données
* @return Bouton de classification
* Renvoie le bouton de classification de données.
* @return Bouton utilisé pour déclencher la classification des données.
*/
public Button getClassifyData() {
return this.classifyData;
......
......@@ -9,10 +9,12 @@ import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Modèle de classification des données.
* Gère le chargement, l'ajout et la classification des données.
*/
public class ClassificationModel extends Observable {
private List<LoadableData> datas;
private List<LoadableData> dataToClass;
......@@ -20,33 +22,36 @@ public class ClassificationModel extends Observable {
private static ClassificationModel model;
/**
* Renvoie une instance unique du model. Par default le type de ce modele est Iris.
* Modifier en .setType(DataType).
* @return l'instance du model
* Renvoie une instance unique du modèle. Par défaut, le type de ce modèle est Iris.
* @return l'instance du modèle
*/
public static ClassificationModel getClassificationModel() {
if(model == null) model = new ClassificationModel();
return model;
}
/**
* Constructeur privé par défaut.
* Initialise le modèle avec le type de données Iris.
*/
private ClassificationModel() {
this(DataType.IRIS);
}
/**
* Constructeur privé avec type de données.
* @param type type de données à utiliser pour la classification.
*/
private ClassificationModel(DataType type) {
this.datas = new ArrayList<>();
this.dataToClass = new CopyOnWriteArrayList<>();
this.type = type;
}
/**
* Ajoute un point au nuage de points avec toutes les données de ce point
* @param coords toutes les données du points
* @throws IllegalArgumentException Exception levée si le nombre de parametres est insuffisant pour creer un point du type du model
* Ajoute un point au nuage de points avec toutes les données de ce point.
* @param coords toutes les données du point.
*/
public void ajouterDonnee(double... coords) {
LoadableData newData = PointFactory.createPoint(type, coords);
......@@ -54,59 +59,78 @@ public class ClassificationModel extends Observable {
notifyObservers(newData);
}
/**
* TODO
* @param file
* Charge les données à partir d'un fichier CSV.
* @param file fichier contenant les données à charger.
*/
public void loadData(File file) throws IOException {
this.datas = new CsvToBeanBuilder<LoadableData>(Files.newBufferedReader(file.toPath()))
.withSeparator(',')
.withType(Iris.class)
.build().parse();
Set<String> types = new HashSet<>();
for (LoadableData d : datas) {
types.add(d.getClassification());
public void loadData(File file) {
try {
this.datas = new CsvToBeanBuilder<LoadableData>(Files.newBufferedReader(file.toPath()))
.withSeparator(',')
.withType(Iris.class)
.build().parse();
Set<String> types = new HashSet<>();
for (LoadableData d : datas) {
types.add(d.getClassification());
}
LoadableData.setClassificationTypes(types);
notifyObservers();
} catch (IOException e) {
System.err.println("Erreur lors du chargement des données : " + e.getMessage());
}
LoadableData.setClassificationTypes(types);
notifyObservers();
}
/**
* Classifie toutes les données à classifier.
* Parcourt la liste des données à classifier et appelle la méthode pour chaque donnée.
*/
public void classifierDonnees() {
dataToClass.forEach(this::classifierDonnee);
}
/**
* TODO
* @param data
* Classifie une donnée spécifique.
* Attribue une classification aléatoire à la donnée fournie et notifie les observateurs.
* @param data donnée à classifier.
*/
private void classifierDonnee(LoadableData data) {
List<String> classes = new ArrayList<>(LoadableData.getClassificationTypes());
Random rdm = new Random();
data.setClassification(classes.get(rdm.nextInt(classes.size())));
notifyObservers(data);
dataToClass.remove(data);
}
/**
* Définit le type de données à classifier.
* @param type type de données.
*/
public void setType(DataType type) {
this.type = type;
}
/**
* Renvoie la liste des données chargées.
* @return liste des données chargées.
*/
public List<LoadableData> getDatas() {
return datas;
}
/**
* Renvoie la liste des données à classifier.
* @return liste des données à classifier.
*/
public List<LoadableData> getDataToClass() {
return dataToClass;
}
/**
* Renvoie le type de données actuellement défini.
* @return type de données.
*/
public DataType getType() {
return type;
}
......
......@@ -3,8 +3,11 @@ package fr.univlille.sae.classification.model;
import com.opencsv.bean.CsvBindByName;
import javafx.scene.paint.Color;
public class Iris extends LoadableData{
/**
* Représente un point Iris.
* Contient des informations sur les dimensions des sépales et des pétales et sur la variété de la fleur.
*/
public class Iris extends LoadableData {
@CsvBindByName(column = "sepal.length")
private double sepalLength;
......@@ -17,24 +20,50 @@ public class Iris extends LoadableData{
@CsvBindByName(column = "variety")
private String variety;
/**
* Constructeur pour créer une instance de Iris avec les dimensions des sépales et des pétales.
* @param sepalLength longueur du sépale.
* @param sepalWidth largeur du sépale.
* @param petalLength longueur du pétale.
* @param petalWidth largeur du pétale.
*/
public Iris(double sepalLength, double sepalWidth, double petalLength, double petalWidth) {
this(sepalLength, sepalWidth, petalLength, petalWidth, "undefined");
}
/**
* Constructeur par défaut.
*/
public Iris() {
//
}
/**
* Renvoie la classification (variété) de l'Iris.
* @return variété de l'Iris.
*/
@Override
public String getClassification() {
return variety;
}
/**
* Définit la classification (variété) de l'Iris.
* @param classification variété à définir.
*/
@Override
public void setClassification(String classification) {
this.variety = classification;
}
/**
* Constructeur pour créer une instance de Iris avec tous les attributs.
* @param sepalLength longueur du sépale.
* @param sepalWidth largeur du sépale.
* @param petalLength longueur du pétale.
* @param petalWidth largeur du pétale.
* @param variety variété de l'Iris.
*/
public Iris(double sepalLength, double sepalWidth, double petalLength, double petalWidth, String variety) {
super();
this.sepalWidth = sepalWidth;
......@@ -44,24 +73,45 @@ public class Iris extends LoadableData{
this.variety = variety;
}
/**
* Renvoie la largeur du sépale.
* @return largeur du sépale.
*/
public double getSepalWidth() {
return sepalWidth;
}
/**
* Renvoie la longueur du sépale.
* @return longueur du sépale.
*/
public double getSepalLength() {
return sepalLength;
}
/**
* Renvoie la largeur du pétale.
* @return largeur du pétale.
*/
public double getPetalWidth() {
return petalWidth;
}
/**
* Renvoie la longueur du pétale.
* @return longueur du pétale.
*/
public double getPetalLength() {
return petalLength;
}
public double getDataType(String axes){
switch (axes){
/**
* Renvoie la valeur des données en fonction de l'axe spécifié.
* @param axes nom de l'axe pour lequel la valeur est requise.
* @return valeur correspondante.
*/
public double getDataType(String axes) {
switch (axes) {
case "sepalWidth":
return sepalWidth;
case "sepalLength":
......@@ -75,8 +125,12 @@ public class Iris extends LoadableData{
}
}
public Color getColor(){
switch (this.variety){
/**
* Renvoie la couleur associée à la variété de l'Iris.
* @return couleur correspondant à la variété.
*/
public Color getColor() {
switch (this.variety) {
case "Setosa":
return Color.RED;
case "Versicolor":
......@@ -84,10 +138,14 @@ public class Iris extends LoadableData{
case "Virginica":
return Color.GREEN;
default:
return Color.BLACK;
return Color.BLACK; // Couleur par défaut si la variété est inconnue
}
}
/**
* Renvoie les noms des attributs de l'Iris.
* @return tableau de chaînes contenant les noms des attributs.
*/
public String[] getAttributesName() {
return new String[]{
"sepalLength",
......@@ -97,6 +155,10 @@ public class Iris extends LoadableData{
};
}
/**
* Représentation sous forme de chaîne de l'objet Iris.
* @return chaîne contenant les dimensions de l'Iris.
*/
@Override
public String toString() {
return "Iris{" +
......
......@@ -4,30 +4,63 @@ import javafx.scene.paint.Color;
import java.util.Set;
/**
* Classe abstraite représentant des données pouvant être chargées.
*/
public abstract class LoadableData {
private static Set<String> classificationTypes;
/**
* Constructeur par défaut.
*/
protected LoadableData() {
}
public abstract String getClassification() ;
/**
* Renvoie la classification de l'objet.
* @return classification sous forme de chaîne.
*/
public abstract String getClassification();
/**
* Renvoie les types de classification définis.
* @return ensemble de types de classification.
*/
public static Set<String> getClassificationTypes() {
return classificationTypes;
}
/**
* Définit les types de classification disponibles.
* @param classificationTypes ensemble de types de classification à définir.
*/
public static void setClassificationTypes(Set<String> classificationTypes) {
LoadableData.classificationTypes = classificationTypes;
}
/**
* Définit la classification de l'objet.
* @param classification classification à définir.
*/
public abstract void setClassification(String classification);
/**
* Renvoie les noms des attributs de l'objet.
* @return tableau de chaînes contenant les noms des attributs.
*/
public abstract String[] getAttributesName();
/**
* Renvoie la couleur associée à l'objet.
* @return couleur correspondant à la classification de l'objet.
*/
public abstract Color getColor();
/**
* Renvoie la valeur des données en fonction de l'axe spécifié.
* @param axes nom de l'axe pour lequel la valeur est requise.
* @return valeur correspondante.
*/
public abstract double getDataType(String axes);
}
package fr.univlille.sae.classification.model;
/**
* Usine pour créer des objets LoadableData en fonction du type de données.
*/
public class PointFactory {
public static LoadableData createPoint(DataType type, double[] coords) {
/**
* Crée un point de données en fonction du type spécifié et des coordonnées fournies.
* @param type type de données
* @param coords coordonnées du point à créer.
* @return instance de LoadableData correspondant aux coordonnées, ou null en cas d'erreur.
* @throws IllegalArgumentException si le nombre de coordonnées ne correspond pas au type spécifié.
*/
public static LoadableData createPoint(DataType type, double[] coords) {
int size = coords.length;
LoadableData data;
switch (type) {
case IRIS:
if(size != 4) throw new IllegalArgumentException();
data = new Iris(coords[0],coords[1],coords[2],coords[3]);
break;
default:
throw new IllegalArgumentException();
try {
switch (type) {
case IRIS:
if (size != 4) {
throw new IllegalArgumentException("Le nombre de coordonnées doit être de 4 pour le type IRIS.");
}
data = new Iris(coords[0], coords[1], coords[2], coords[3]);
break;
default:
throw new IllegalArgumentException("Type de données non supporté : " + type);
}
} catch (IllegalArgumentException e) {
System.err.println("Erreur lors de la création du point : " + e.getMessage());
return null;
}
return data;
......
......@@ -3,20 +3,33 @@ package fr.univlille.sae.classification.utils;
import java.util.Collection;
import java.util.HashSet;
/**
* Classe abstraite représentant un sujet observable.
*/
public abstract class Observable {
protected Collection<Observer> attached = new HashSet<>();
protected Collection<Observer> toDetach = new HashSet<>();
/**
* Attache un observateur à l'objet observable.
* @param obs observateur à attacher.
*/
public void attach(Observer obs) {
attached.add(obs);
}
/**
* Détache un observateur de l'objet observable.
* @param obs observateur à détacher.
*/
public void detach(Observer obs) {
this.toDetach.add(obs);
}
/**
* Notifie tous les observateurs attachés de tout changement.
*/
protected void notifyObservers() {
this.updateList();
for (Observer o : attached) {
......@@ -24,6 +37,10 @@ public abstract class Observable {
}
}
/**
* Notifie tous les observateurs attachés avec des données supplémentaires.
* @param data données à transmettre aux observateurs.
*/
protected void notifyObservers(Object data) {
this.updateList();
for (Observer o : attached) {
......@@ -31,9 +48,11 @@ public abstract class Observable {
}
}
/**
* Met à jour la liste des observateurs attachés en supprimant ceux à détacher.
*/
private void updateList() {
this.attached.removeAll(toDetach);
this.toDetach.clear();
}
}
......@@ -6,8 +6,18 @@ import javafx.scene.control.MenuItem;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
/**
* Classe utilitaire pour la gestion des vues.
*/
public class ViewUtil {
/**
* Définit la couleur de la forme
* @param iris objet de données à afficher.
* @param form forme à configurer.
* @param root scène principale pour le menu contextuel.
* @return forme configurée.
*/
public static Shape getForm(LoadableData iris, Shape form, Stage root) {
try {
form.setFill(iris.getColor());
......
......@@ -11,18 +11,30 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* Classe responsable de la création et de l'affichage de la vue d'ajout de données.
*/
public class AddDataView {
private ClassificationModel model;
private Stage owner;
private MainStageView mainStageView;
/**
* Constructeur pour initialiser la vue d'ajout de données.
* @param model le modèle de classification utilisé pour gérer les données.
* @param owner la fenêtre parente de cette vue.
* @param mainStageView la vue principale associée.
*/
public AddDataView(ClassificationModel model, Stage owner, MainStageView mainStageView) {
this.model = model;
this.owner = owner;
this.mainStageView = mainStageView;
}
/**
* Charge le fichier FXML et initialise la scène.
*/
public void show() {
FXMLLoader loader = new FXMLLoader();
URL fxmlFileUrl = null;
......
......@@ -12,18 +12,30 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* Classe responsable de la création et de l'affichage de la vue de configuration des axes.
*/
public class AxesSettingsView {
private ClassificationModel model;
private Stage owner;
private DataVisualizationView dataVisualizationView;
/**
* Constructeur pour initialiser la vue de configuration des axes.
* @param model modèle de classification utilisé pour gérer les données.
* @param owner fenêtre parente de cette vue.
* @param dataVisualizationView vue de visualisation des données associée.
*/
public AxesSettingsView(ClassificationModel model, Stage owner, DataVisualizationView dataVisualizationView) {
this.model = model;
this.owner = owner;
this.dataVisualizationView = dataVisualizationView;
}
/**
* Affiche la vue de configuration des axes.
*/
public void show() {
FXMLLoader loader = new FXMLLoader();
URL fxmlFileUrl = null;
......
......@@ -13,8 +13,6 @@ import javafx.fxml.FXMLLoader;
import javafx.scene.chart.XYChart;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import java.io.File;
......@@ -23,19 +21,26 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Classe responsable de l'affichage et de la gestion de la vue des données.
* Implémente l'interface Observer pour recevoir des notifications de mise à jour.
*/
public class DataStageView extends DataVisualizationView implements Observer {
private ClassificationModel model;
private DataStageController controller;
private XYChart.Series series1 ;
private XYChart.Series series2 ;
private XYChart.Series series3 ;
private XYChart.Series series4 ;
private XYChart.Series series1;
private XYChart.Series series2;
private XYChart.Series series3;
private XYChart.Series series4;
private Stage root;
/**
* Constructeur pour initialiser la vue de données.
* @param model le modèle de classification utilisé pour gérer les données.
*/
public DataStageView(ClassificationModel model) {
super();
this.model = model;
......@@ -46,31 +51,31 @@ public class DataStageView extends DataVisualizationView implements Observer {
model.attach(this);
}
/**
* Affiche la vue des données en chargeant le fichier FXML et en initialisant la scène.
*/
public void show() {
FXMLLoader loader = new FXMLLoader();
try {
URL fxmlFileUrl = new File(System.getProperty("user.dir") + File.separator + "res" + File.separator + "stages" + File.separator + "data-view-stage.fxml").toURI().toURL();
if (fxmlFileUrl == null) {
System.out.println("Impossible de charger le fichier fxml");
System.exit(-1);
}
loader.setLocation(fxmlFileUrl);
root = loader.load();
root.setResizable(false);
root.setTitle("SAE3.3 - Logiciel de classification");
root.show();
loader.getController();
controller = loader.getController();
controller.setDataStageView(this);
scatterChart = controller.getScatterChart();
scatterChart.getData().addAll(series4, series1, series2, series3 );
if (fxmlFileUrl == null) {
System.out.println("Impossible de charger le fichier fxml");
System.exit(-1);
}
loader.setLocation(fxmlFileUrl);
root = loader.load();
root.setResizable(false);
root.setTitle("SAE3.3 - Logiciel de classification");
root.show();
controller = loader.getController();
controller.setDataStageView(this);
scatterChart = controller.getScatterChart();
scatterChart.getData().addAll(series4, series1, series2, series3);
controller.setAxesSelected("Aucun fichier sélectionné");
controller.setAxesSelected("Aucun fichier sélectionné");
if (!model.getDatas().isEmpty()) {
update(model);
......@@ -80,6 +85,10 @@ public class DataStageView extends DataVisualizationView implements Observer {
}
}
/**
* Met à jour l'affichage des données en fonction des changements dans le modèle.
* @param observable modèle observé.
*/
@Override
public void update(Observable observable) {
try {
......@@ -91,63 +100,57 @@ public class DataStageView extends DataVisualizationView implements Observer {
ObservableList<XYChart.Series> series = scatterChart.getData();
for(XYChart.Series serie : series) {serie.getData().clear();}
//Jalon 1: on verifie que le type de donnée est bien IRIS
if(model.getType() == DataType.IRIS) {
if(actualX==null && actualY==null){
controller.setAxesSelected("Aucuns axes sélectionnés");
}
else{
controller.setAxesSelected("");
//On recupere les données du model
List<LoadableData> points = new ArrayList<>(model.getDatas());
points.addAll(model.getDataToClass());
// on ajoute chaque point a la serie
for(LoadableData i : points) {
Iris iris = (Iris)i;
XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>(iris.getDataType(actualX),
iris.getDataType(actualY));
if (model.getType() == DataType.IRIS) {
if (actualX == null && actualY == null) {
controller.setAxesSelected("Aucuns axes sélectionnés");
}
else {
controller.setAxesSelected("");
//On recupere les données du model
List<LoadableData> points = new ArrayList<>(model.getDatas());
points.addAll(model.getDataToClass());
// on ajoute chaque point a la serie
for (LoadableData i : points) {
Iris iris = (Iris) i;
XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>(iris.getDataType(actualX),
iris.getDataType(actualY));
dataPoint.setNode(ViewUtil.getForm(iris, new Circle(5), root));
switch (iris.getClassification()) {
case "Setosa":
series1.getData().add(dataPoint);
break;
case "Versicolor":
series2.getData().add(dataPoint);
break;
case "Virginica":
series3.getData().add(dataPoint);
break;
default:
dataPoint.setNode(ViewUtil.getForm(iris, new Rectangle(10, 10), root));
series4.getData().add(dataPoint);
break;
switch (iris.getClassification()) {
case "Setosa":
series1.getData().add(dataPoint);
break;
case "Versicolor":
series2.getData().add(dataPoint);
break;
case "Virginica":
series3.getData().add(dataPoint);
break;
default:
dataPoint.setNode(ViewUtil.getForm(iris, new Rectangle(10, 10), root));
series4.getData().add(dataPoint);
break;
}
series1.setName("Setosa");
series2.setName("Versicolor");
series3.setName("Virginica");
series4.setName("indefini");
}
series1.setName("Setosa");
series2.setName("Versicolor");
series3.setName("Virginica");
series4.setName("undefinied");
}
}
}
} catch (Exception e) {
System.err.println("Erreur de mise à jour : " + e.getMessage());
}
}
/**
* Met à jour l'affichage en ajoutant un nouveau point de données.
* @param observable modèle observé.
* @param data point de données à ajouter.
*/
@Override
public void update(Observable observable, Object data) {
try {
......@@ -166,20 +169,27 @@ public class DataStageView extends DataVisualizationView implements Observer {
iris.getDataType(actualY)
);
dataPoint.setNode(ViewUtil.getForm(iris, new Rectangle(10, 10), root));
if (!scatterChart.getData().isEmpty()) {
series4.getData().add(dataPoint);
dataPoint.setNode(ViewUtil.getForm(iris, new Rectangle(10, 10), root));
if (!scatterChart.getData().isEmpty()) {
series4.getData().add(dataPoint);
}
}
}
} catch (Exception e) {
System.err.println("Erreur de mise à jour : " + e.getMessage());
}
}
/**
* Renvoie le contrôleur associé à cette vue.
* @return contrôleur de la vue.
*/
public DataStageController getController() {
return controller;
}
/**
* Recharge les données de la vue en fonction des données du modèle.
*/
@Override
public void reload() {
this.update(ClassificationModel.getClassificationModel());
......
......@@ -2,31 +2,63 @@ package fr.univlille.sae.classification.view;
import javafx.scene.chart.ScatterChart;
/**
* Classe abstraite représentant une vue de visualisation des données.
* Elle gère les axes actuels et le graphique de dispersion.
*/
public abstract class DataVisualizationView {
protected DataVisualizationView() {}
protected String actualX;
protected String actualY;
protected ScatterChart scatterChart;
/**
* Constructeur par défaut.
*/
protected DataVisualizationView() {}
/**
* Renvoie le nom de l'axe X actuel.
* @return nom de l'axe X.
*/
public String getActualX() {
return actualX;
}
/**
* Définit le nom de l'axe X actuel.
* @param actualX nom de l'axe X à définir.
*/
public void setActualX(String actualX) {
this.actualX = actualX;
}
/**
* Renvoie le nom de l'axe Y actuel.
* @return nom de l'axe Y.
*/
public String getActualY() {
return actualY;
}
/**
* Définit le nom de l'axe Y actuel.
* @param actualY nom de l'axe Y à définir.
*/
public void setActualY(String actualY) {
this.actualY = actualY;
}
/**
* Renvoie le graphique de dispersion associé à cette vue.
* @return graphique de dispersion.
*/
public ScatterChart getScatterChart() {
return this.scatterChart;
}
/**
* Méthode abstraite à implémenter pour recharger les données de la vue.
*/
public abstract void reload();
}
......@@ -9,16 +9,27 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* Classe responsable de l'affichage de la vue de chargement des données.
*/
public class LoadDataView {
private ClassificationModel model;
private Stage owner;
/**
* Constructeur de la vue de chargement des données.
* @param model modèle de classification à utiliser.
* @param owner fenêtre parente.
*/
public LoadDataView(ClassificationModel model, Stage owner) {
this.model = model;
this.owner = owner;
}
/**
* Affiche la fenêtre de chargement des données.
*/
public void show() {
FXMLLoader loader = new FXMLLoader();
URL fxmlFileUrl = null;
......
......@@ -8,18 +8,11 @@ import fr.univlille.sae.classification.model.LoadableData;
import fr.univlille.sae.classification.utils.Observable;
import fr.univlille.sae.classification.utils.Observer;
import fr.univlille.sae.classification.utils.ViewUtil;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.control.*;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import java.io.File;
......@@ -29,6 +22,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* Classe représentant la vue principale de l'application de classification.
*/
public class MainStageView extends DataVisualizationView implements Observer {
private ClassificationModel model;
......@@ -36,68 +32,68 @@ public class MainStageView extends DataVisualizationView implements Observer {
private Stage root;
private XYChart.Series series1 ;
private XYChart.Series series2 ;
private XYChart.Series series1;
private XYChart.Series series2;
private XYChart.Series series3;
private XYChart.Series series4 ;
private XYChart.Series series4;
/**
* Constructeur de la vue principale.
* @param model modèle de classification à utiliser.
*/
public MainStageView(ClassificationModel model) {
super();
this.series1 = new XYChart.Series();
this.series2 = new XYChart.Series();
this.series3 = new XYChart.Series();
this.series4 = new XYChart.Series();
this.model = model;
model.attach(this);
}
/**
* Affiche la vue principale.
*/
public void show() {
FXMLLoader loader = new FXMLLoader();
try {
URL fxmlFileUrl = new File(System.getProperty("user.dir") + File.separator + "res" + File.separator + "stages" + File.separator + "main-stage.fxml").toURI().toURL();
if (fxmlFileUrl == null) {
System.out.println("Impossible de charger le fichier fxml");
System.exit(-1);
}
loader.setLocation(fxmlFileUrl);
root = loader.load();
root.setResizable(false);
root.setTitle("SAE3.3 - Logiciel de classification");
root.show();
root.setOnCloseRequest(event -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirmation");
alert.setHeaderText("Voulez vous quitter l'application ?");
alert.setContentText("Aucunes modifications ne sera sauvegardé ! Les points qui ont été ajoutés ne seront pas sauvegardés");
Optional<ButtonType> optionalButtonType = alert.showAndWait();
if(optionalButtonType.isPresent() && optionalButtonType.get() == ButtonType.OK) {
System.exit(0);
}else {
event.consume();
if (fxmlFileUrl == null) {
System.out.println("Impossible de charger le fichier fxml");
System.exit(-1);
}
loader.setLocation(fxmlFileUrl);
root = loader.load();
root.setResizable(false);
root.setTitle("SAE3.3 - Logiciel de classification");
root.show();
root.setOnCloseRequest(event -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirmation");
alert.setHeaderText("Voulez-vous quitter l'application ?");
alert.setContentText("Aucunes modifications ne seront sauvegardées ! Les points ajoutés ne seront pas sauvegardés.");
Optional<ButtonType> optionalButtonType = alert.showAndWait();
if (optionalButtonType.isPresent() && optionalButtonType.get() == ButtonType.OK) {
System.exit(0);
} else {
event.consume();
}
});
});
loader.getController();
controller = loader.getController();
controller.setMainStageView(this);
scatterChart = controller.getScatterChart();
scatterChart.getData().addAll(series1, series2, series3, series4);
System.out.println("DataStageView scatter chart: " +scatterChart );
controller.setAxesSelected("Aucun fichier sélectionné");
controller = loader.getController();
controller.setMainStageView(this);
scatterChart = controller.getScatterChart();
scatterChart.getData().addAll(series1, series2, series3, series4);
controller.setAxesSelected("Aucun fichier sélectionné");
} catch (IOException e) {
System.err.println("Erreur lors du chargement du fichier FXML : " + e.getMessage());
}
}
@Override
public void update(Observable observable) {
try {
......@@ -107,62 +103,51 @@ public class MainStageView extends DataVisualizationView implements Observer {
}
ObservableList<XYChart.Series> series = scatterChart.getData();
for(XYChart.Series serie : series) {serie.getData().clear();}
//Jalon 1: on verifie que le type de donnée est bien IRIS
if(model.getType() == DataType.IRIS) {
if(actualX==null && actualY==null){
controller.setAxesSelected("Aucuns axes sélectionnés");
for (XYChart.Series serie : series) {
serie.getData().clear();
}
else{
controller.setAxesSelected("");
if (model.getType() == DataType.IRIS) {
if (actualX == null && actualY == null) {
controller.setAxesSelected("Aucuns axes sélectionnés");
} else {
controller.setAxesSelected("");
List<LoadableData> points = new ArrayList<>(model.getDatas());
points.addAll(model.getDataToClass());
for (LoadableData i : points) {
Iris iris = (Iris) i;
XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>(iris.getDataType(actualX),
iris.getDataType(actualY));
XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>(iris.getDataType(actualX), iris.getDataType(actualY));
dataPoint.setNode(ViewUtil.getForm(iris, new Circle(5), root));
switch (iris.getClassification()) {
case "Setosa":
series1.getData().add(dataPoint);
break;
case "Versicolor":
series2.getData().add(dataPoint);
break;
case "Virginica":
series3.getData().add(dataPoint);
break;
default:
dataPoint.setNode(ViewUtil.getForm(iris, new Rectangle(10, 10), root));
series4.getData().add(dataPoint);
break;
switch (iris.getClassification()) {
case "Setosa":
series1.getData().add(dataPoint);
break;
case "Versicolor":
series2.getData().add(dataPoint);
break;
case "Virginica":
series3.getData().add(dataPoint);
break;
default:
dataPoint.setNode(ViewUtil.getForm(iris, new Rectangle(10, 10), root));
series4.getData().add(dataPoint);
break;
}
}
series1.setName("Setosa");
series2.setName("Versicolor");
series3.setName("Virginica");
series4.setName("indéfini");
}
series1.setName("Setosa");
series2.setName("Versicolor");
series3.setName("Virginica");
series4.setName("undefinied");
}
}
}catch (Exception e) {
}
} catch (Exception e) {
System.err.println("Erreur de mise à jour : " + e.getMessage());
}
}
@Override
public void update(Observable observable, Object data) {
try {
......@@ -170,9 +155,9 @@ public class MainStageView extends DataVisualizationView implements Observer {
System.err.println("Erreur de mise à jour.");
return;
}
if(data instanceof Iris) {
if (data instanceof Iris) {
Iris iris = (Iris) data;
if(actualX == null || actualY == null) {
if (actualX == null || actualY == null) {
controller.setAxesSelected("Aucuns axes sélectionnés");
return;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment