diff --git a/res/stages/data-view-stage.fxml b/res/stages/data-view-stage.fxml index 4eaff3a517f37cf2129ee0f95c841f2182c4ff82..7adaf2e98d4a5a148fa0e36cdce53bb08f9e63ca 100644 --- a/res/stages/data-view-stage.fxml +++ b/res/stages/data-view-stage.fxml @@ -6,37 +6,55 @@ <?import javafx.scene.control.*?> <?import javafx.scene.image.*?> <?import javafx.scene.layout.*?> +<?import javafx.scene.text.*?> <?import javafx.stage.*?> -<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> +<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.DataStageController"> <scene> <Scene> - <AnchorPane prefHeight="363.0" prefWidth="692.0"> + <AnchorPane prefHeight="487.0" prefWidth="692.0"> <children> - <VBox prefHeight="363.0" prefWidth="691.0"> + <VBox prefHeight="488.0" prefWidth="691.0"> <children> - <HBox prefHeight="356.0" prefWidth="691.0"> + <HBox alignment="TOP_CENTER" prefHeight="356.0" prefWidth="691.0" spacing="5.0"> <children> - <Region prefHeight="338.0" prefWidth="65.0" /> - <ScatterChart prefHeight="342.0" prefWidth="609.0"> - <xAxis> - <CategoryAxis fx:id="absAxeView" prefHeight="21.0" prefWidth="498.0" side="BOTTOM" /> - </xAxis> - <yAxis> - <NumberAxis fx:id="ordAxeView" side="LEFT" /> - </yAxis> - </ScatterChart> - <Button fx:id="settingsView" mnemonicParsing="false"> - <graphic> - <ImageView fitHeight="100.0" fitWidth="30.0" pickOnBounds="true" preserveRatio="true"> - <image> - <Image url="@gear.png" /> - </image></ImageView> - </graphic> + <AnchorPane prefHeight="200.0" prefWidth="200.0"> + <children> + <Region prefHeight="338.0" prefWidth="65.0" /> + <ScatterChart fx:id="scatterChart" prefHeight="342.0" prefWidth="609.0"> + <xAxis> + <NumberAxis fx:id="absAxe" prefHeight="21.0" prefWidth="498.0" side="BOTTOM" /> + </xAxis> + <yAxis> + <NumberAxis fx:id="ordAxe" side="LEFT" /> + </yAxis> + </ScatterChart> + <Label fx:id="AxesSelected" alignment="CENTER" layoutX="175.0" layoutY="152.0" prefHeight="38.0" prefWidth="259.0"> + <font> + <Font size="21.0" /> + </font></Label> + </children> <HBox.margin> - <Insets right="10.0" top="30.0" /> + <Insets left="10.0" /> </HBox.margin> - </Button> + </AnchorPane> + <Button fx:id="settingsView" mnemonicParsing="false" onAction="#openAxesSetting"> + <graphic> + <ImageView fitHeight="100.0" fitWidth="30.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@gear.png" /> + </image> + </ImageView> + </graphic> + <HBox.margin> + <Insets top="40.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + <HBox alignment="CENTER" prefHeight="169.0" prefWidth="691.0" spacing="50.0"> + <children> + <Button fx:id="classifyData" disable="true" mnemonicParsing="false" onAction="#classifyDatas" prefHeight="26.0" prefWidth="157.0" text="Classifier les données" /> </children> </HBox> </children> diff --git a/res/stages/main-stage.fxml b/res/stages/main-stage.fxml index 21c1941b9e1627e260b3f2c5f765e0bc59535401..d96791c6fc56edec5a2bb01d5b71bdb294fcdaa2 100644 --- a/res/stages/main-stage.fxml +++ b/res/stages/main-stage.fxml @@ -9,7 +9,7 @@ <?import javafx.scene.text.*?> <?import javafx.stage.*?> -<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> +<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> <scene> <Scene> <AnchorPane prefHeight="487.0" prefWidth="692.0"> @@ -52,13 +52,18 @@ </Button> </children> </HBox> - <HBox alignment="CENTER" prefHeight="169.0" prefWidth="691.0" spacing="50.0"> + <VBox alignment="TOP_CENTER" prefHeight="200.0" prefWidth="100.0"> <children> - <Button fx:id="loadData" mnemonicParsing="false" onAction="#openLoadData" prefHeight="27.0" prefWidth="185.0" text="Charger un jeu de données" /> - <Button fx:id="addData" mnemonicParsing="false" onAction="#openAddData" prefHeight="26.0" prefWidth="141.0" text="Ajouter une donnée" /> - <Button fx:id="classifyData" disable="true" mnemonicParsing="false" onAction="#classifyDatas" prefHeight="26.0" prefWidth="157.0" text="Classifier les données" /> + <HBox alignment="CENTER" prefHeight="85.0" prefWidth="691.0" spacing="50.0"> + <children> + <Button fx:id="loadData" mnemonicParsing="false" onAction="#openLoadData" prefHeight="27.0" prefWidth="185.0" text="Charger un jeu de données" /> + <Button fx:id="addData" mnemonicParsing="false" onAction="#openAddData" prefHeight="26.0" prefWidth="141.0" text="Ajouter une donnée" /> + <Button fx:id="classifyData" disable="true" mnemonicParsing="false" onAction="#classifyDatas" prefHeight="26.0" prefWidth="157.0" text="Classifier les données" /> + </children> + </HBox> + <Button alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#openDataView" text="Ouvrir une autre vue" /> </children> - </HBox> + </VBox> </children> </VBox> </children></AnchorPane> diff --git a/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java b/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java index 370a3a2fb7effe974b6f2500759a3b74980e7fb9..1a690a0d60ea419913197b982e16a872a530bae8 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java @@ -2,6 +2,7 @@ package fr.univlille.sae.classification.controller; import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.Iris; +import fr.univlille.sae.classification.view.DataVisualizationView; import fr.univlille.sae.classification.view.MainStageView; import javafx.fxml.FXML; import javafx.scene.control.*; diff --git a/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java b/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java index 8c890f287f75bcf97175c66402b68f004278a50e..16c52b1329fb9fd7842620cba9c2f817ef54300e 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java @@ -1,7 +1,7 @@ package fr.univlille.sae.classification.controller; import fr.univlille.sae.classification.model.ClassificationModel; -import fr.univlille.sae.classification.view.MainStageView; +import fr.univlille.sae.classification.view.DataVisualizationView; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ChoiceBox; @@ -21,31 +21,31 @@ public class AxesSettingsController{ @FXML Button confirmAxes; - MainStageView mainStageView; + DataVisualizationView dataVisualizationView; public void setSelectOrd(String[] fields){ selectOrd.getItems().clear(); selectOrd.getItems().addAll(fields); - selectOrd.setValue(mainStageView.getActualY()); + selectOrd.setValue(dataVisualizationView.getActualY()); } public void setSelectAbs(String[] fields){ selectAbs.getItems().clear(); selectAbs.getItems().addAll(fields); - selectAbs.setValue(mainStageView.getActualX()); + selectAbs.setValue(dataVisualizationView.getActualX()); } - public void setMainStageView(MainStageView mainStageView) { - this.mainStageView = mainStageView; + public void setdataVisualizationView(DataVisualizationView dataVisualizationView) { + this.dataVisualizationView = dataVisualizationView; } public void validate(){ - mainStageView.setActualX(selectAbs.getValue().toString()); - mainStageView.setActualY(selectOrd.getValue().toString()); - mainStageView.getController().getScatterChart().getXAxis().setLabel(mainStageView.getActualX()); - mainStageView.getController().getScatterChart().getYAxis().setLabel(mainStageView.getActualY()); + dataVisualizationView.setActualX(selectAbs.getValue().toString()); + dataVisualizationView.setActualY(selectOrd.getValue().toString()); + dataVisualizationView.getScatterChart().getXAxis().setLabel(dataVisualizationView.getActualX()); + dataVisualizationView.getScatterChart().getYAxis().setLabel(dataVisualizationView.getActualY()); - mainStageView.update(ClassificationModel.getClassificationModel()); + dataVisualizationView.reload(); stage.close(); } } diff --git a/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java b/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java new file mode 100644 index 0000000000000000000000000000000000000000..2c561a9baeefbb69af581d0a69a7654c44783130 --- /dev/null +++ b/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java @@ -0,0 +1,78 @@ +package fr.univlille.sae.classification.controller; + +import fr.univlille.sae.classification.model.ClassificationModel; +import fr.univlille.sae.classification.view.*; +import javafx.fxml.FXML; +import javafx.scene.chart.NumberAxis; +import javafx.scene.chart.ScatterChart; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.stage.Stage; + +import java.io.IOException; + + +public class DataStageController { + @FXML + Stage stage; + + @FXML + NumberAxis absAxe; + + @FXML + NumberAxis ordAxe; + + @FXML + Button settings; + + @FXML + Button loadData; + + @FXML + Button classifyData; + + @FXML + ScatterChart scatterChart; + + @FXML + Label AxesSelected; + + Stage loadStage; + private DataStageView dataStageView; + + /** + * Ouvre l'interface de chargement des données. + * @throws IOException + */ + public void openLoadData() throws IOException { + LoadDataView loadDataView = new LoadDataView(ClassificationModel.getClassificationModel(), stage); + loadDataView.show(); + } + + public void openAxesSetting()throws IOException { + AxesSettingsView axesSettingsView = new AxesSettingsView(ClassificationModel.getClassificationModel(), stage, dataStageView); + axesSettingsView.show(); + } + + public void setDataStageView (DataStageView dataStageView) { + this.dataStageView = dataStageView; + } + + public void classifyDatas() { + ClassificationModel.getClassificationModel().classifierDonnees(); + classifyData.setDisable(true); + } + + + public ScatterChart getScatterChart() { + return this.scatterChart; + } + + public void setAxesSelected(String texte) { + this.AxesSelected.setText(texte); + } + + public Button getClassifyData() { + return this.classifyData; + } +} diff --git a/src/main/java/fr/univlille/sae/classification/controller/DataViewStage.java b/src/main/java/fr/univlille/sae/classification/controller/DataViewStage.java deleted file mode 100644 index fe7a9b0083d0ef2abc3ac4a22eb5be0faae92c5c..0000000000000000000000000000000000000000 --- a/src/main/java/fr/univlille/sae/classification/controller/DataViewStage.java +++ /dev/null @@ -1,22 +0,0 @@ -package fr.univlille.sae.classification.controller; - -import javafx.fxml.FXML; -import javafx.scene.chart.CategoryAxis; -import javafx.scene.chart.NumberAxis; -import javafx.scene.control.Button; -import javafx.stage.Stage; - -public class DataViewStage { - - @FXML - Stage stage; - - @FXML - CategoryAxis absAxe; - - @FXML - NumberAxis ordAxe; - - @FXML - Button settings; -} diff --git a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java index bf9f71772b2d4d293772505e2f4e0b38e2b9f693..bf8ab81524503f95f0e79d146a92a2da1545ab7d 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java @@ -1,10 +1,7 @@ package fr.univlille.sae.classification.controller; import fr.univlille.sae.classification.model.ClassificationModel; -import fr.univlille.sae.classification.view.AxesSettingsView; -import fr.univlille.sae.classification.view.LoadDataView; -import fr.univlille.sae.classification.view.AddDataView; -import fr.univlille.sae.classification.view.MainStageView; +import fr.univlille.sae.classification.view.*; import javafx.fxml.FXML; import javafx.scene.chart.*; @@ -59,6 +56,11 @@ public class MainStageController { loadDataView.show(); } + public void openDataView() throws IOException { + DataStageView dataStageView = new DataStageView(ClassificationModel.getClassificationModel()); + dataStageView.show(); + } + public void openAxesSetting()throws IOException { AxesSettingsView axesSettingsView = new AxesSettingsView(ClassificationModel.getClassificationModel(), stage, mainStageView); axesSettingsView.show(); diff --git a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java index f52b777a7d536b07d41032a0b6412eed913807fa..8b404aa681e721888ea94b8df97fa13ab727f9b6 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java @@ -24,8 +24,6 @@ public class AddDataView { this.mainStageView = mainStageView; } - - public void show() throws IOException { FXMLLoader loader = new FXMLLoader(); diff --git a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java index 48ca4ce0f1b8e3369cc350672cb210b2a0bb39e2..2a1f23424e2d78a964eaae7a13df1d7b1f23802f 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java @@ -1,6 +1,7 @@ package fr.univlille.sae.classification.view; import fr.univlille.sae.classification.controller.AxesSettingsController; +import fr.univlille.sae.classification.controller.DataStageController; import fr.univlille.sae.classification.controller.MainStageController; import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.LoadableData; @@ -9,6 +10,7 @@ import javafx.scene.control.Alert; import javafx.stage.Modality; import javafx.stage.Stage; +import javax.xml.crypto.Data; import java.io.File; import java.io.IOException; import java.net.URL; @@ -18,12 +20,12 @@ public class AxesSettingsView { private ClassificationModel model; private Stage owner; - private MainStageView mainStageView; + private DataVisualizationView dataVisualizationView; - public AxesSettingsView(ClassificationModel model, Stage owner, MainStageView mainStageView){ + public AxesSettingsView(ClassificationModel model, Stage owner, DataVisualizationView dataVisualizationView){ this.model = model; this.owner = owner; - this.mainStageView = mainStageView; + this.dataVisualizationView = dataVisualizationView; } public void show() throws IOException { @@ -44,7 +46,7 @@ public class AxesSettingsView { root.setTitle("Configuration des axes"); AxesSettingsController controller = loader.getController(); - controller.setMainStageView(mainStageView); + controller.setdataVisualizationView(dataVisualizationView); if(model.getDatas().isEmpty()) { Alert alert = new Alert(Alert.AlertType.WARNING); diff --git a/src/main/java/fr/univlille/sae/classification/view/DataStageView.java b/src/main/java/fr/univlille/sae/classification/view/DataStageView.java new file mode 100644 index 0000000000000000000000000000000000000000..2cf2f84225f9101e4a4a766392047b18c07b11a4 --- /dev/null +++ b/src/main/java/fr/univlille/sae/classification/view/DataStageView.java @@ -0,0 +1,149 @@ +package fr.univlille.sae.classification.view; + +import fr.univlille.sae.classification.controller.DataStageController; +import fr.univlille.sae.classification.controller.MainStageController; +import fr.univlille.sae.classification.model.ClassificationModel; +import fr.univlille.sae.classification.model.DataType; +import fr.univlille.sae.classification.model.Iris; +import fr.univlille.sae.classification.model.LoadableData; +import fr.univlille.sae.classification.utils.Observable; +import fr.univlille.sae.classification.utils.Observer; +import javafx.fxml.FXMLLoader; +import javafx.scene.chart.ScatterChart; +import javafx.scene.chart.XYChart; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.shape.Circle; +import javafx.stage.Stage; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +public class DataStageView extends DataVisualizationView implements Observer { + + private ClassificationModel model; + private DataStageController controller; + + private Stage root; + + public DataStageView(ClassificationModel model) { + this.model = model; + model.attach(this); + } + + public void show() throws IOException { + FXMLLoader loader = new FXMLLoader(); + + 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(); + controller.setAxesSelected("Aucun fichier sélectionné"); + + if (!model.getDatas().isEmpty()) { + update(model); + } + } + + @Override + public void update(Observable observable) { + if(scatterChart == null) throw new IllegalStateException(); + if(!(observable instanceof ClassificationModel)) throw new IllegalStateException(); + //on vide le nuage pour s'assurer que celui-ci est bien vide + scatterChart.getData().clear(); + + XYChart.Series series1 = new XYChart.Series(); + series1.setName("Iris"); + + //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 ajoute la serie au nuage + scatterChart.getData().add(series1); + + //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(getCircle(iris)); + + series1.getData().add(dataPoint); + + } + } + } + } + + + private Circle getCircle(Iris iris) { + Circle circle = new Circle(5); + circle.setFill(iris.getColor()); + circle.setOnMouseClicked(e -> { + ContextMenu contextMenu = new ContextMenu(); + for(String attributes : iris.getAttributesName()) { + contextMenu.getItems().add(new MenuItem(attributes + " : " + iris.getDataType(attributes))); + } + contextMenu.show(root, e.getScreenX(), e.getScreenY()); + }); + + return circle; + } + + + + @Override + public void update(Observable observable, Object data) { + if(scatterChart == null) throw new IllegalStateException(); + if(!(observable instanceof ClassificationModel)) throw new IllegalStateException(); + if(data instanceof Iris) { + Iris iris = (Iris) data; + if(actualX == null || actualY == null) { + controller.setAxesSelected("Aucuns axes sélectionnés"); + return; + } + XYChart.Data<Double, Double> dataPoint = new XYChart.Data<>( + iris.getDataType(actualX), + iris.getDataType(actualY) + ); + + dataPoint.setNode(getCircle(iris)); + if (!scatterChart.getData().isEmpty()) { + XYChart.Series series = (XYChart.Series) scatterChart.getData().get(0); + series.getData().add(dataPoint); + } + } + } + + public DataStageController getController() { + return controller; + } + + @Override + public void reload() { + this.update(ClassificationModel.getClassificationModel()); + } +} diff --git a/src/main/java/fr/univlille/sae/classification/view/DataVisualizationView.java b/src/main/java/fr/univlille/sae/classification/view/DataVisualizationView.java new file mode 100644 index 0000000000000000000000000000000000000000..fd6757379be8e74f0903511c25872f56b27db1cd --- /dev/null +++ b/src/main/java/fr/univlille/sae/classification/view/DataVisualizationView.java @@ -0,0 +1,32 @@ +package fr.univlille.sae.classification.view; + +import javafx.scene.chart.ScatterChart; + +public abstract class DataVisualizationView { + protected DataVisualizationView() {} + protected String actualX; + protected String actualY; + protected ScatterChart scatterChart; + + public String getActualX() { + return actualX; + } + + public void setActualX(String actualX) { + this.actualX = actualX; + } + + public String getActualY() { + return actualY; + } + + public void setActualY(String actualY) { + this.actualY = actualY; + } + + public ScatterChart getScatterChart() { + return this.scatterChart; + } + + public abstract void reload(); +} diff --git a/src/main/java/fr/univlille/sae/classification/view/MainStageView.java b/src/main/java/fr/univlille/sae/classification/view/MainStageView.java index 9fe2d12ccfa1a9f28748a435b0db46fd9fc83443..78545eedf055ab4c96c3051096169b79efc20afc 100644 --- a/src/main/java/fr/univlille/sae/classification/view/MainStageView.java +++ b/src/main/java/fr/univlille/sae/classification/view/MainStageView.java @@ -24,14 +24,11 @@ import java.io.IOException; import java.net.URL; import java.util.*; -public class MainStageView implements Observer { +public class MainStageView extends DataVisualizationView implements Observer { private ClassificationModel model; - private ScatterChart scatterChart; private MainStageController controller; - private String actualX; - private String actualY; private Stage root; public MainStageView(ClassificationModel model) { @@ -144,24 +141,12 @@ public class MainStageView implements Observer { } } - public void setActualX(String actualX) { - this.actualX = actualX; - } - - public void setActualY(String actualY) { - this.actualY = actualY; - } - - public String getActualX() { - return actualX; - } - - public String getActualY() { - return actualY; - } - public MainStageController getController() { return controller; } + @Override + public void reload() { + this.update(ClassificationModel.getClassificationModel()); + } }