Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction aux composants JTable, JTree et JGraph

Introduction aux composants JTable, JTree et JGraph

Support de cours concernant les composants JTable, JTree et JGraph qui permettent la visualisation d'informations avec le langage Java. Le support décrit comment modifier le rendu de l'affichage et le composant Editor (celui qui est utilisé pour effectuer une édition) et comment exploiter les différents modèles : modèle du composant et modèle de sélection notamment.

3c4219fa12e875f02a81d5957876de8e?s=128

Mickael BARON

November 28, 2006
Tweet

Transcript

  1. Java pour le développement de clients lourds Mickaël BARON -

    2006 (Révision Août 2010) mailto:baron.mickael@gmail.com ou mailto:baron@ensma.fr Visualisation d’informations : JTree, JTable et JGraph
  2. 2 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Creative Commons Contrat Paternité Partage des Conditions Initiales à l'Identique 2.0 France http://creativecommons.org/licenses/by-sa/2.0/fr Licence
  3. 3 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : objets graphiques adaptés † Cette partie s’intéresse à présenter des composants en Java permettant la visualisation et la manipulation d’informations de grande quantité † Les informations peuvent être présentées sous forme de tableau, d’arbre ou de graphe † L’API Java Swing propose nativement deux composants complexes pour la visualisation d’informations † Tableau avec JTable † Arbre avec JTree † La représentation sous forme de graphe n’est pas encore proposée par Sun et nous utiliserons la bibliothèque † Graphe avec JGraph
  4. 4 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : objets graphiques adaptés Composant JTable Composant JTree Composant JGraph
  5. 5 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : objets graphiques adaptés † L’objectif principale de cette partie est de vous montrer comment paramétrer ces composants † Modification du rendu des informations † Modification du rendu d’édition † Ajout et suppression dynamique d’éléments † Manipulation des modèles (contenu et de sélection) † Technique de prévisualisation et zoom † Impression et génération d’images † Ressources † JTree : java.sun.com/docs/books/tutorial/uiswing/components/tree.hml † JTable : java.sun.com/docs/books/tutorial/uiswing/components/table.html † JGraph : www.jgraph.com Nous présenterons dans cette partie les choses à faire et à ne pas faire
  6. 6 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    M Visualisation d’informations : objets graphiques adaptés † Les composants complexes et d’autres composants respectent le modèle d’architecture MVC (Model View Controller) † L’implémentation proposée par Java/Swing se rapproche plus du Document/Vue ou Model/View (le contrôleur étant associé à la vue) † Principe de l’architecture † Le modèle est l’élément principale du composant † La ou les vue(s) du composant sont abonnées au modèle † La modèle notifie ses vues suite à des modifications La partie Document (En Java le vue et le contrôleur ne sont pas dissociés) La partie Modèle (Notification des vues après modification) V C
  7. 7 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : présentation générale † Avec le composant JTable vous pouvez afficher les données sous forme de table et éditer les données à partir des cellules † Un composant JTable doit être ajouté à un container JScollPane et non à un simple JPanel Les cellules sont éditables On peut ajouter des composants autre que des JLabel Les données par colonne sont typées et formatées JTable myTable = new JTable(...); JScrollPane myScrollPane = new JScrollPane(myTable); JScrollPane myScrollPane = new JScrollPane(); myScrollPane.add(myTable); Affiche la JTable avec des ascenseurs si besoin La JTable n’est pas visible
  8. 8 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    † Le modèle JTable doit implémenter l’interface TableModel † Deux implémentations existent pour faciliter l’utilisation du modèle TableModel (méthodes supplémentaires) † La classe abstraite AbstractTableModel † La classe DefaultTableModel † Le fonctionnement du modèle dépend de l’implémentation des méthodes (ou redéfinition) † int getRowCount() : retourne le nombre de ligne † int getColumnCount() : retourne le nom de colonne † Object getValueAt(int row, int column) : retourne l’objet pour la cellule † setValueAt(Object, int row, int co) : nouvelle valeur de la cellule JTable : création du modèle Méthode abstraites dans la classe AbstractTableModel Vue JTable Modèle TableModel
  9. 9 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : création du modèle † Le fonctionnement du modèle dépend de l’implémentation des méthodes (suite) † Class getColumnClass(int cc) : type de la colonne † boolean isCellEditable(int r, int l) : indique si la cellule est modifiable † String getColumnName(int coIn) : nom de la colonne pour coIn † addTableModelListener(TableModelListener) : ajoute un écouteur qui est notifié à chaque fois que le modèle est modifié † Des méthodes (issues des sous-classes de TableModel) n’ont pas à être redéfinies et peuvent être utilisées † fireTableDataChanged() : notifie toutes les vues de modifications † fireTableRowsUpdated(int fr, int lr) : notifie entre les lignes fr et lr † L’interface TableModelListener contient une méthode † tableChanged(TableModelEvent e) : appelée à la suite de chaque modification du modèle
  10. 10 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : création du modèle † Exemple : une première JTable et son modèle public class MyTableModel extends AbstractTableModel { private String[] columnNames = ... private Object[][] data = ... public int getColumnCount() {return columnNames.length;} public int getRowCount() {return data.length;} public String getColumnName(int col) {return columnNames[col];} public Object getValueAt(int row, int col) {return data[row][col];} public Class getColumnClass(int c) {return getValueAt(0,c).getClass();} public boolean isCellEditable(int row, int col) {return (col < 2);} public void setValueAt(Object value, int row, int col) { data[row][col] = value; fireTableCellUpdated(row,col) } } public class MyTableDemo implements TableModelListener { public MyTableDemo() { JTable myTable = new JTable(new MyTableModel()); myTable.getModel().addTableModelListener(); ... } public void tableChanged(TableModelEvent e) { System.out.println("Coucou"); } } Préférez ce mode de construction d’une JTable avec un modèle explicite Notification explicite des modifications aux vues Optimisation des notifications en choisissant le bon fire
  11. 11 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors et Renderers † Une JTable (JTree et JGraph fonctionnent un principe commun) dispose de classes spécifiques pour effectuer † un rendu des cellules appelée classe Renderer † une édition des données des cellules appelée classe Editor † Un objet Editor est appelé quand l’utilisateur effectue une action sur la cellule (sous condition que la cellule soit éditable) † Un objet Renderer est une vue sans réaction directe qui retourne une visualisation de la données de la cellule L’objet Editor associé à cette colonne affiche un JComboBox pour l’édition d’une chaîne de caractères L’objet Renderer utilisé pour cette cellule affiche un JLabel
  12. 12 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors et Renderers † Principe d’appel des objets Editor et Renderer Utilisateur déplace la fenêtre et sélectionne les cellules 1 Les renderers affiche les données du modèle getValueAt(…) Utilisateur clique sur une cellule éditable L’objet Editor est appelé. La valeur courante de la cellule est retournée à l’objet Editor 2 Utilisateur termine l’édition L’objet Editor retourne la nouvelle valeur qui est retournée au modèle setValueAt(…) 3
  13. 13 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors et Renderers † Il existe par défaut des objets Editor et Renderer définis dans la JTable † Rappelons que getColumnClass() retourne le type de l’objet de la cellule † Selon le type de données se trouvant dans le modèle (indi- qué par getColumnClass()) les objets Editor et Renderer retournent des composants prédéfinis † Composant retourné par l’objet Renderer † Boolean : JCheckBox † Number, Double et Float : JLabel aligné à droite † ImageIcon : JLabel aligné au centre † Composant retourné par l’objet Editor † Boolean : JCheckBox † Autre : JTextField
  14. 14 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors et Renderers † Possibilité de modifier les objets Renderer et Editor de manière à paramétrer la visualisation et l’édition † La JTable propose plusieurs manières de modifier ces objets † Un Renderer et/ou Editor par type d’objet (Class) † Un Renderer et/ou Editor par colonne † Si vous souhaitez associer un Renderer et un Editor pour toutes les colonnes qui ont le même type utiliser la première solution † Si vous souhaitez effectuer un Renderer et un Editor ponctu- elle pour une colonne utilisez la seconde solution † Quelle que soit la solution les Renderer/Editor sont les mêmes. Seuls la liaison entre les Renderer/Editor et la JTable change † Nous présenterons les deux solutions …
  15. 15 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors et Renderers † Première solution : un Renderer/Editor par type d’objet † setDefaultRenderer(Class, TableCellRenderer) : associe un Renderer au type défini par le paramètre Class † setDefaultEditor(Class, TableCellEditor) : associe un Editor à un type † Toutes les colonnes dont le type est associé à un Renderer/Editor a une visualisation et/ou édition personnalisée † Deuxième solution : un Renderer/Editor par colonne † Extraire le modèle de colonne TableColumnModel getcolumnModel() † A partir du TablecolumnModel choisir la colonne qui vous intéresse à paramétrer : TableColumn getColumn(int) † Modifier le Renderer/Editor † setCellEditor(TableCellEditor) : associe l’Editor à la colonne † setCellRenderer(TableCellRenderer) : lie le Renderer à la colonne Si vous mixez les deux solutions c’est le Renderer/Editor par la colonne qui prend le dessus
  16. 16 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors et Renderers † Exemple : associer les Renderer/Editor à une JTable public class JTableDirectRenderer1 extends JFrame { public MyTableDemo() { ... JTable myTable = new JTable(new MyDefaultTableModel()); myTable.setDefaultEditor(Integer.class, new MyAbstractCellEditor()); myTable.setDefaultEditor(Boolean.class, new MyAbstractCellEditorBoolean()); myTable.setDefaultRenderer(Boolean.class, new MyAbstractCellRenderer()); TableColumnModel myColumnModel = myTable.getColumnModel(); TableColumn myTableColumn = myColumnModel.getColumn(0); myTableColumn.setCellEditor(new MySecondAbstractCellEditor()); myTableColumn.setCellRenderer(new TableCellRenderer() { public Component getTableCellRendererComponent(JTable, ...) { return new JButton((String)arg1); } }); } } Modification des Editors pour les colonne dont la classe est de type Integer et Boolean Modification du Renderer pur la colonne Boolean Modification des Renderer/Editor pour la colonne 0
  17. 17 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Renderers † Un Renderer doit implémenter l’interface TableCellRenderer † Cette interface possède une méthode unique qui retourne le composant à afficher dans la cellule † Component getTableCellRendererComponent(JTable table, Object v, boolean isSelected, boolean hasFocus, int row, int column) † JTable table : référence de la JTable associé au Renderer † Object v : valeur à afficher du modèle obtenue par getValueAt(…) † boolean isSelected : la cellule est-elle sélectionnée ? † boolean hasFocus : la cellule a-t-elle le focus ? † int row : numéro de ligne de la cellule considérée † int column : numéro de colonne de la cellule considérée † Il faut donc retourner un objet graphique Component qui sera utilisé pour effectuer le rendu de la cellule Le composant de retour n’a pas de « réaction » il est utilisé pour effectuer un rendu = image
  18. 18 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Renderers † Exemple : un Renderer personnalisé pour les types Boolean public class MyAbstractCellRenderer implements TableCellRenderer { private JToggleButton vraie = new JToggleButton(); public Component getTableCellRendererComponent(JTable arg0, Object arg1, boolean arg2, boolean arg3, int arg4, int arg5) { Boolean myBool = (Boolean )arg1; vraie.setSelected(myBool.booleanValue()); return vraie; } } Le composant chargé du rendu est construit à la construction de la classe Récupère la valeur qui doit être affichée (getValueAt(…) du modèle) Modifie la valeur du composant et le retourne au Renderer pour affichage Le composant JCheckBox a été remplacé par un JToogleButton Le Renderer initial
  19. 19 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors † Un Editor doit implémenter l’interface TableCellEditor qui hérite également de l’interface CellEditor utilisée par tous les objets ayant un Editor : JTree, JTable, JListBox, … † Cette interface possède entre autre une méthode qui retourne le composant à afficher pour l’édition † Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) † JTable table : référence de la JTable associé à l’Editor † Object value : valeur de la cellule (pas uniquement un String) † boolean isSelected : la cellule est-elle sélectionnée † int row : numéro de ligne de la cellule † int column : numéro de la colonne † Pour éviter d’implémenter toutes les méthodes de l’interface CellEditor vous pouvez utiliser la classe AbstractCellEditor
  20. 20 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors † Si la classe AbstractCellEditor est utilisée en place de CellEditor certaines méthodes ont un comportement prédéfini † stopCellEditing() : déclenche l’arrêt de l’Editor † cancelCellEditing() : déclenche l’annulation de l’Editor † addCellEditorListener(CellEditorListener) : ajoute un écouteur d’édition † … † Cependant vous devrez fournir obligatoirement une implémentation de la méthode † Object getCellEditorValue() : la valeur que l’utilisateur vient de saisir (méthode setValueAt(…) du modèle est alors appelée) † Principe de codage † Implémentez getTableCellEditorComponent(…) pour retourner le composant d’édition † La validation du composant d’édition doit appeler stopCellEditing() † Implémentez getCellEditorValue()
  21. 21 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : Editors † Exemple : un Editor personnalisé pour les types Boolean public class MyAbstractCellEditorBoolean extends AbstractCellEditor implements TableCellEditor { private JToggleButton myButton = new JToggleButton(); public MyAbstractCellEditorBoolean() { myButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ MyAbstractCellEditorBoolean.this.fireEditingStopped(); } }); } public Object getCellEditorValue() { return new Boolean(myButton.isSelected()); } public Component getTableCellEditorComponent(JTable arg0, Object arg1, boolean arg2, int arg3, int arg4) { Boolean myBool = (Boolean )arg1; myButton.setSelected(myBool.booleanValue()); return myButton; } } L’action du bouton permet de valider la valeur qui vient d’être saisie Cette méthode retourne au modèle la nouvelle valeur (setValueAt(…) du modèle) L’initialisation du composant qui se charge de l’édition
  22. 22 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : modèle de sélection † Le modèle de sélection permet de gérer les aspects liés à la sélection de lignes ou de colonnes (une ou plusieurs …) † Un modèle de sélection doit implémenter l’interface appelée ListSelectionModel † Possibilité de modifier un modèle de sélection pour toutes les lignes et un modèle de sélection pour toutes les colonnes † JTable#setSelectionModel(ListSelectionModel) : modifie le modèle de sélection pour les lignes † TableColumnModel#setSelectionModel(ListSelectionModel) : modifie le modèle de sélection pour toutes les colonnes † Pour écouter le changement de sélection de lignes ou de colonnes ajoutez un écouteur sur le modèle de sélection † ListSelectionModel#addListSelectionListener(ListSelectionListener) : ajoute un écouteur de sélection
  23. 23 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : modèle de sélection † La définition explicite du modèle de sélection n’est utile que si vous souhaitez effectuer des traitements pointus sur les sélections † Pour le reste des aspects liés à la sélection utilisez les méthodes de la classe JTable qui pointent directement sur le modèle de sélection † setSelectionMode(int) : choix du modèle de sélection † SINGLE_SELECTION : une seule cellule peut-être sélectionnée † MULTIPLE_INTERVAL_SELECTION : plusieurs cellules sélection- nées à des moments différents † SINGLE_INTERVAL_SELECTION : plusieurs cellules sélectionnées en même temps † int getSelectedColumn() : indice de la colonne sélectionnée † int getSelectedRow() : indice de la ligne sélectionnée † clearSelection() : supprime la sélection actuelle
  24. 24 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : modèle de sélection † Trois différents modes de sélection Mode de sélection à SINGLE_SELECTION Mode de sélection à SINGLE_INTERVAL_SELECTION Mode de sélection à MULTIPLE_INTERVAL_SELECTION
  25. 25 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : modèle de sélection † Exemple : accès aux informations de la sélection courante public class JTableDirectRenderer2 extends JFrame { ... public JTableExemple() { ... myTable.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { System.out.println("Ligne:" + myTable.getSelectedRow()); System.out.println("Colonne:" + myTable.getSelectedColumn()); } }); ... } ... Sortie « console » Réaction au clic sur la JTable Méthodes liées à la sélection disponibles directement dans la classe JTable
  26. 26 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : ajout et suppression dynamique † L’ajout et la suppression dynamique de ligne se fait en ajou- tant ou en supprimant des éléments au contenu sémantique de la JTable † Rappelons que la méthode getRowCount() et getValueAt(…) sont appelées pour « peupler » la table † Une solution est d’ajouter au modèle deux méthodes † addRow(Object p, int pRow) : ajoute l’objet p à la ligne pRow † removeRow(int pRow) : supprime la ligne pRow † Le modèle n’est pas à même de connaître la ligne d’ajout ou la ligne à supprimer tout dépend de la ligne sélectionnée † Ajout : ligne suivante de celle sélectionnée ou dernière ligne † Suppression : ligne en cours de sélection † A chaque ajout ou suppression d’une ligne n’oubliez pas de notifier la vue des modifications apportées au modèle
  27. 27 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : ajout et suppression dynamique † Exemple : ajout et suppression de ligne dans une JTable public class MyDefaultSecondTableModel extends AbstractTableModel { private ArrayList colonneName = new ArrayList(); private ArrayList colonneLastName = new ArrayList(); ... public void addNewRow(int ligne) { int addline = getRowCount(); if (ligne != -1) addline = ligne +1; colonneName.add(addline, "Name"); colonneLastName.add(addline, "First Name"); ... this.fireTableStructureChanged(); } public void removeNewRow(int ligne) { if (getRowCount() == 0 || ligne < 0) return; colonneName.remove(ligne); colonneLastName.remove(ligne); ... this.fireTableStructureChanged(); } ... } Transformer les tableaux en ArrayList pour l’ajout dynamique des objets Une méthode pour ajouter des lignes Une méthode pour supprimer des lignes Notification à l’ensemble des vues pour avertir que le modèle a changé
  28. 28 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : ajout et suppression dynamique † Exemple (suite) : ajout et sup. de ligne dans une JTable public class JTableDirectRenderer3 extends JFrame { ... public JTableExemple() { JButton myAddButton = new JButton("Ajouter"); myAddButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { MyDefaultTableModel refModel = (MyDefaultTableModel)myTable.getModel(); refModel.addNewRow(myTable.getSelectedRow()); } }); JButton myRemoveButton = new JButton("Supprimer"); myRemoveButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { MyDefaultTableModel refModel = (MyDefaultTableModel)myTable.getModel(); refModel.removeNewRow(myTable.getSelectedRow()); } }); } ... Identifie le modèle du composant JTable Récupère l’indice de la lige sélectionnée Deux boutons pour ajouter ou supprimer des lignes
  29. 29 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTable : bilan JTable TableModel 1 ListSelectionModel 1 TableCellEditor TableCellRenderer 1 .. >= Colonne 1 .. >= Colonne † Un composant JTable est une vue paramétrable qui permet d’afficher et modifier des données d’une table Paramétrage de l’affichage des données Modification des données Données du composant Sélection des données Grâce au pattern MVC de Java il est possible de brancher un modèle existant à une autre vue (voir le composant JGraph pour un exemple) TableModelListener 0..n CellEditorListener 0..n ListSelectionListener 0..n Ecouteur pour avertir que l’édition est annulée ou validée Ecouteur pour avertir que le modèle a changé Ecouteur pour avertir que la sélection a changé
  30. 30 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : présentation générale † Avec le composant JTree vous pouvez afficher les données sous forme d’arbre, plier/déplier des nœuds et les éditer † Un composant JTree doit être ajouté à un container JScollPane et non à un simple JPanel Un nœud père qui contient quatre nœuds fils Le nœud racine, il est unique et ne possède pas de parent Un nœud feuille et fils du nœud « colors » Des icônes pour représenter l’état des nœuds JTree myTree = new JTree(...); JScrollPane myScrollPane = new JScrollPane(myTree); JScrollPane myScrollPane = new JScrollPane(); myScrollPane.add(myTree); Affiche le JTree avec des ascenseurs si besoin Le JTree n’est pas visible dans ce cas là
  31. 31 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : gestion des noeuds † L’interface MutableTreeNode (hérite de TreeNode) fournit un service de gestion et de manipulation des données de l’arbre † Un MutableTreeNode modélise un nœud de l’arbre. La classe DefaultMutableTreeNode est une implémentation par défaut † add(MutableTreeNode p) : ajoute p comme dernier enfant noeud † int getChildCount() : retourne le nombre d’enfant du nœud † TreeNode getParent() : retourne le nœud parent † TreeNode getChildAt(int p) : retourne l’enfant de l’indice p † insert(MutableTreeNode child, int index) : ajout l’enfant à la position indice † remove(MutableTreeNode child) : supprime le nœud child † isLeaf() : le nœud est une feuille ou pas, …
  32. 32 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : gestion des noeuds † Chaque nœud peut contenir un objet utilisateur † setUserObject(Object object) : modifie l’objet du nœud † Object getUserObject() : récupère l’objet du nœud † Un objet DefaultMutableTreeNode peut être construit à partir d’un objet utilisateur : DefaultMutableTreeNode(Object user) † Par défaut, le texte affiché pour chaque nœud correspond à l’objet utilisateur retourné par sa méthode toString() (étudié plus en détail dans le Render/Editor du JTree) † Par comparaison avec la JTable l’objet utilisateur est l’objet retourné par getValueAt() du modèle † Un composant JTree affiche l’objet DefaultMutableTreeNode qui correspond au nœud racine appelé « root »
  33. 33 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : gestion des noeuds † Exemple : manipulation d’un objet DefaultMutableTreeNode public JTreeExample1() { DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Père de tous"); DefaultMutableTreeNode childNode = new DefaultMutableTreeNode("Enfant Raoul"); rootNode.add(childNode); childNode = new DefaultMutableTreeNode("Enfant Gasper"); rootNode.add(childNode); childNode = new DefaultMutableTreeNode("Enfant Leon"); rootNode.add(childNode); DefaultMutableTreeNode childChildNode = new DefaultMutableTreeNode("Petit Leon"); childNode.add(childChildNode); childChildNode = new DefaultMutableTreeNode("Petit Leon second"); childNode.add(childChildNode); System.out.println("Nombre d'enfants : " + rootNode.getChildCount()); System.out.println("Nombre d'enfants ayant des petits enfants : " + rootNode.getSiblingCount()); System.out.println("Objet du noeud racine : " + rootNode.getUserObject()); rootNode.setUserObject("Père de tous M"); JTree myJTree = new JTree(rootNode); JScrollPane myScrollPane = new JScrollPane(myJTree); this.getContentPane().add(myScrollPane()); ... } } Ajout de nœuds dans le nœud racine Les nœuds sont construits avec un objet utilisateur de type String
  34. 34 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : création du modèle † Le modèle d’un JTree propose un ensemble de fonction- nalités pour manipuler les nœuds de l’arbre † Le point de départ du modèle est le nœud « root ». En effet un modèle pour un JTree est construit avec le nœud racine † L’interface TreeModel s’occupe de décrire le modèle de l’arbre. DefaultTreeModel est une implémentation par défaut † DefaultTreeModel(TreeNode p) : modèle avec un nœud racine † Object getChild(Object parent, int index) : retourne l’enfant de l’indice index du parent parent † int getchildCount(Object parent) : nombre d’enfants de parent † Object getRoot() : retourne le nœud racine de l’arbre † boolean isLeaf(Object node) : détermine node est une feuille Les objets en paramètre et en retour ne sont pas des MutableTreeNode. Vous pouvez proposez votre structure en implémentant votre propre modèle (TreeModel)
  35. 35 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : création du modèle † Les méthodes du modèle sont utilisées de la même manière que celles du modèle de la JTable † Principe de fonctionnement † la méthode getChildCount(…) détermine le nombre d’enfant du nœud † la méthode getChild(…) pour le même parent sera appelée autant de fois que la valeur retournée par getChildCount(…) † En plus des méthodes d’interrogation des nœuds il est possible d’écouter les modifications du modèle † addTreeModelListener(TreeModelListener l) : ajouter un écouteur † treeNodesChanged(TreeNodeEvent) : un nœud a été changé (le contenu) † treeStructureChanged(TreeNodeEvent) : un nœud a été déplacé † … Les méthodes d’ajout et de suppression seront vues plus loin
  36. 36 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : création du modèle † Exemple : ne montrer que les enfants du nœud racine public MyTreeModel extends DefaultTreeModel { public MyTreeModel(MutableTreeNode p) { super(p); } public Object getChild(Object arg0, int arg1) { return ((DefaultMutableTreeNode) arg0).getChildAt(arg1); } public int getChildCount(Object arg0) { if (arg0 != root) return 0; DefaultMutableTreeNode myTreeNode = (DefaultMutableTreeNode) arg0; return myTreeNode.getChildCount(); } public boolean isLeaf(Object arg0) { if (arg0 == root) return false; } return true; } } JTree myTree = new JTree(new MyTreeModel(root)); JScrollPane myScrollPane = new JScrollPane(myTable); ... Ne pas oublier de donner le nœud racine au modèle Pour chaque nœud on compte le nombre d’enfants Détermine si le nœud est une feuille ou pas
  37. 37 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Editors et Renderers † Un JTree dispose de classes spécifiques pour effectuer † Un rendu des noeuds appelée classe Renderer † Une édition des données des noeuds appelée classe Editor † Un objet Editor est appelé quand l’utilisateur effectue une action d’édition sur le noeud (sous condition que le nœud soit éditable) † Un objet Renderer est une vue sans réaction directe qui retourne une visualisation du nœud (objet utilisateur) L’objet Renderer utilisé par défaut est un JLabel L’objet Editor utilisé par défaut est un JTextField
  38. 38 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Editors et Renderers † Principe d’appel des objets Editor et Renderer Utilisateur déplace la fenêtre et sélectionne un noeud Le Renderer affiche les données de chaque MutableTreeNode Utilisateur clique sur un noeud éditable L’objet Editor est appelé. La valeur courante du noeud est retournée à l’objet Editor. Utilisateur termine l’édition L’objet Editor retourne la nouvelle valeur qui est transmise au MutableTreeNode éditée 3 1 2
  39. 39 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Editors et Renderers † Le composant JTree ne manipule pas de ligne ni de colonne comme un composant JTable † A la différence du composant JTable les objets Renderer et Editor sont applicables à tous les nœuds de l’arbre † JTree#setCellRenderer(TreeCellRenderer) : modifie un objet Renderer † JTree#setCellEditor(TreeCellEditor) : modifie un objet Editor public class JTreeExample3 extends JFrame { public MyJTree() { ... JTree myTree = new JTree(new MyDefaultTreeModel()); JScrollPane myScrollPane = new JScrollPane(myTree); myTree.setCellRenderer(new MyTreeCellRenderer()); myTree.setCellEditor(new MyTreeCellEditor()); ... } } Modification de l’Editor de l’objet myTree Modification du Renderer de l’objet myTree
  40. 40 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Renderers † Un Renderer doit implémenter l’interface TreeCellRenderer † Cette interface possède une méthode unique qui retourne le composant à afficher dans la cellule † Component getTreeCellRendererComponent(JTree tree, Object v, boolean isSel, boolean exp, boolean leaf, int row, boolean hFocus) † JTree tree : référence de la JTree associé au Renderer † Object v : le nœud en cours de rendu † boolean isSel : le nœud est-il sélectionné ? † boolean exp : le nœud est-il déplié ? † boolean leaf : le nœud est-il une feuille † int row : le numéro d’indice de l’enfant † boolean hFocus : le composant à la focus † Il faut donc retourner un objet graphique Component qui sera utilisé pour effectuer le rendu du noeud Le composant de retour n’a pas de « réaction » il est utilisé pour effectuer un rendu = image
  41. 41 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Renderers † Exemple : un Renderer personnalisé public class MyDefaultTreeCellRenderer implements TreeCellRenderer { public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { JLabel myLabel = new JLabel(); JLabel labelExpanded = new JLabel(); if (value instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode myNode = (DefaultMutableTreeNode)value; String infoText = "- "; if (selected) infoText += "S "; if (leaf) myLabel.setIcon(new ImageIcon("middle.gif")); else myLabel.setIcon(new ImageIcon("pig.gif")); if (expanded) labelExpanded.setIcon(new ImageIcon("exp.gif")); else labelExpanded.setIcon(new ImageIcon("nexp.gif")); infoText += " L :" + row + " - "; infoText += (String)myNode.getUserObject(); myLabel.setText(infoText); } JPanel myPanel = new JPanel(new BorderLayout()); myPanel.add(BorderLayout.WEST,labelExpanded); myPanel.add(BorderLayout.CENTER,myLabel); return myPanel; } L’objet envoyé au Renderer est un objet de type MutableTreeNode Nous retournons ici un composant JPanel (par défaut il s’agit d’un composant JLabel)
  42. 42 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Editors † Un Editor doit implémenter l’interface TreeCellEditor qui hérite également de l’interface CellEditor † Cette interface possède entre autre une méthode qui retourne le composant à afficher pour l’édition † Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) † JTree tree : référence de la JTree associé à l’Editor † Object value : objet MutableTreeNode en cours d’édition † boolean isSelected : le noeud est-il sélectionné ? † boolean expanded : le nœud est-il déplié ? † boolean leaf : le nœud est-il une feuille ? † int row : le numéro d’indice de l’enfant † Pour éviter d’implémenter toutes les méthodes de l’interface CellEditor vous pouvez utiliser la classe AbstractCellEditor
  43. 43 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Editors † Si la classe AbstractCellEditor est utilisée en place de CellEditor certaines méthodes ont un comportement prédéfini † stopCellEditing() : déclenche l’arrêt de l’Editor † cancelCellEditing() : déclenche l’annulation de l’Editor † addCellEditorListener(CellEditorListener) : ajoute un écouteur d’édition † … † Cependant vous devrez fournir obligatoirement une implémen- tation de la méthode † Object getCellEditorValue() : retourne la valeur que l’utilisateur vient de saisir (la méthode setUserObject(…) du nœud est alors appelée) † Principe de codage † Implémentez getTreeCellEditorComponent(…) pour retourner le composant d’édition † La validation du composant d’édition doit appeler stopCellEditing() † Implémentez getCellEditorValue()
  44. 44 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : Editors † Exemple : un Editor personnalisé public class MyDefaultTreeCellEditor extends AbstractCellEditor implements TreeCellEditor, ActionListener { private JPanel myPanel; private JTextField myText; public MyDefaultTreeCellEditor() { myPanel = new JPanel(); JLabel myLabel = new JLabel("Edition :"); myText = new JTextField(10); myText.addActionListener(this); myPanel.setLayout(new BorderLayout()); myPanel.add(BorderLayout.WEST, myLabel); myPanel.add(BorderLayout.CENTER, myText); } public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { if (value instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode ob = (DefaultMutableTreeNode)value; myText.setText((String)ob.getUserObject()); } return myPanel; } public Object getCellEditorValue() { return myText.getText(); } public void actionPerformed(ActionEvent arg0) { this.stopCellEditing(); } } La méthode qui renvoie la nouvelle valeur de l’utilisateur au nœud édité setUserObject(…) La valeur éditée est celle de l’objet utilisateur
  45. 45 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : modèle de sélection † Le modèle de sélection permet de gérer les aspects liés à la sélection de nœuds (un ou plusieurs) † Un modèle de sélection doit implémenter l’interface appelée TreeSelectionModel † Possibilité de modifier ou de récupérer un modèle de sélection d’un composant JTree † setSelectionModel(TreeSelectionModel) : modifie le modèle de sélection † TreeSelectionModel getSelectionModel() : récupère le modèle de sélection † Pour écouter le changement de sélection de nœuds ajoutez un écouteur sur le modèle de sélection † addTreeSelectionListener(TreeSelectionListener) : ajoute un écouteur de sélection
  46. 46 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : modèle de sélection † La modification du modèle de sélection n’est utile que si vous effectuer des traitements pointus sur les sélections † Curieusement certaines méthodes proposées directement par la classe JTable ne se retrouvent pas dans la classe JTree † setSelectionMode(int) : choix du modèle de sélection † SINGLE_TREE_SELECTION : un seul noeud sélectionné † CONTIGUOUS_TREE_SELECTION : plusieurs noeuds sélectionnés directement liés (lien de voisinage) † DISCONTIGUOUS_TREE_SELECTION : plusieurs nœuds sélection- nés indirectement liés † TreePath getSelectionPath() : retourne le chemin du nœud sélectionné † TreePath[] getSelectionPaths() : retourne les chemins des nœuds sélectionnés Méthodes disponibles à la fois dans la classe JTree et TreeSelectionModel
  47. 47 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : modèle de sélection † Trois différents modes de sélection Mode de sélection à SINGLE_TREE_SELECTION Mode de sélection à CONTIGUOUS_TREE_SELECTION Mode de sélection à DISCONTIGOUS_TREE_SELECTION
  48. 48 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : modèle de sélection † Les méthodes qui permettent de récupérer le ou les nœuds sélectionné(s) retournent un objet TreePath † Un objet TreePath est une sorte de chemin des objets de la racine jusqu’aux objets du nœud sélectionné † Les objets sont normalement des MutableTreeNode † Exemples : « Père de tous », « Enfant Leon » et « Petit Leon » Nœud feuille à l’indice 2 Nœud père à l’indice 1 Nœud racine à l’indice 0
  49. 49 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : modèle de sélection † La classe TreePath possède des méthodes qui permettent d’extraire du ou des chemins sélectionné(s) les nœuds intéressants † Object getLastPathComponent() : objet correspondant au dernier nœud sélectionné (normalement de type MutableTreeNode) † Object getPathComponent(int elem) : objet du nœud à l’indice elem. La tête du chemin correspond à l’indice zéro † TreePath getParentPath() : nouveau chemin excepter le dernier nœud † int getPathCount() : nombre de nœuds inclus dans ce chemin † … Les objets récupérés peuvent être « castés » en une classe de type MutableTreeNode
  50. 50 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : modèle de sélection † Exemple : accès aux informations de la sélection courante ... myJTree.addTreeSelectionListener(new TreeSelectionListener(){ public void valueChanged(TreeSelectionEvent tse) { TreePath myPath = myJTree.getSelectionPath(); DefaultMutableTreeNode myMutable = (DefaultMutableTreeNode)myPath.getPathComponent(0); System.out.println("Racine" + myMutable); System.out.println("Sélection" + (DefaultMutableTreeNode)myPath.getLastPathComponent()); } }); ...
  51. 51 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : ajout et suppression dynamique † Pour ajouter ou supprimer des nœuds dans un JTree, il suffit de manipuler les nœuds parents en ajoutant ou supprimant des nœuds enfants (par défaut la structure est de type MutableTreeNode) † add(MutableTreeNode child) : ajoute le nœud child en dernière position † insert(MutableTreeNode child, int childIndex) : ajoute le nœud child à la position childIndex † remove(int child) : supprime le nœud à l’indice child † remove(MutableTreeNode child) : supprime le nœud child † La classe DefaultTreeModel propose des méthodes qui réalise la même chose † insertNodeInto(MutableTreeNode child, MutableTreeNode par, int ind) : ajoute le nœud child à l’indice ind au nœud par † removeNodeFromParent(MutableTreeNode c) : supprime le nœud c
  52. 52 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : ajout et suppression dynamique † Etapes pour ajouter ou supprimer un nœud † Connaître le nœud parent dans lequel ce nœud va être ajouté (sélec- tion ou au début/fin d’un nœud particulier) † Extraction de l’objet TreePath le futur nœud parent † Ajouter ou supprimer au futur nœud parent le nouveau sous nœud † Mettre à jour le modèle pour qu’il puisse notifier la ou les vues des changements effectués † Déplier complètement l’arborescence du nouveau noeud (par défaut les nouveaux nœuds ne sont pas dépliés) † JTree#scrollPathToVisible(TreePath p) : déplier un chemin † Avertir le modèle d’un éventuel changement (ajout, suppression, modification d’objet, …) † DefaultTreeModel#reload() : recharge le modèle † DefaultTreeModel#reload(TreeNode node) : recharge le modèle par le dessous du nœud node
  53. 53 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : ajout et suppression dynamique † Exemple : ajouter, supprimer et tout supprimer … ... JButton add = new JButton("Ajouter"); add.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { TreePath myPath = myJTree.getSelectionPath(); DefaultMutableTreeNode myParent = (DefaultMutableTreeNode)myPath.getLastPathComponent(); DefaultMutableTreeNode mySon = new DefaultMutableTreeNode("Coucou"); myParent.add(mySon); myJTree.scrollPathToVisible(new TreePath(mySon.getPath())); ((DefaultTreeModel)myJTree.getModel()).reload(myParent); } }); JButton remove = new JButton("Supprimer"); remove.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { TreePath myPath = myJTree.getSelectionPath(); DefaultMutableTreeNode myParent= (DefaultMutableTreeNode)(myPath.getParentPath().getLastPathComponent()); DefaultMutableTreeNode mySon= (DefaultMutableTreeNode)myPath.getLastPathComponent(); myParent.remove(mySon); ((DefaultTreeModel)myJTree.getModel()).reload(myParent); } });
  54. 54 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : ajout et suppression dynamique † Exemple (suite) : ajouter, supprimer et tout supprimer … ... JButton removeAll = new JButton("Tout supprimer"); removeAll.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((DefaultMutableTreeNode)myJTree.getModel().getRoot()).removeAllChildren(); ((DefaultTreeModel)myJTree.getModel()).reload(); } }); Tous les enfants ont été supprimés du nœud racine Mise à jour du modèle après modification
  55. 55 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JTree : bilan JTree TreeModel 1 TreeSelectionModel 1 TreeCellEditor TreeCellRenderer 1 † Un composant JTree est une vue paramétrable qui permet d’afficher et modifier des données d’un arbre Paramétrage de l’affichage des données Modification des données Données du composant Sélection des données Grâce au pattern MVC de Java il est possible de brancher un modèle existant à une autre vue (voir le composant JGraph pour un exemple) TreeModelListener 0..n CellEditorListener 0..n TreeSelectionListener 0..n Ecouteur pour avertir que l’édition est annulée ou validée Ecouteur pour avertir que le modèle a changé Ecouteur pour avertir que la sélection a changé 1
  56. 56 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : présentation générale † Un graphe est un cas particulier d’arbre où les nœuds peuvent posséder plusieurs parents disjoints ou pas † L’API Swing ne propose pas par défaut de composant permettant de représenter des graphes † Utilisation de l’API externe JGraph † Site : www.jgraph.com † Elle fonctionne suivant un principe commun aux composants JTable et JTree dans le sens où elle se fonde sur l’architecture MVC † De nombreux outils utilisent cette bibliothèque et dont la licence est libre d’utilisation sous condition de fournir les sources † Documentation (Tutorial) payante mais JavaDoc ainsi qu’un Forum sont disponibles gratuitement
  57. 57 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : présentation générale
  58. 58 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : présentation générale
  59. 59 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : présentation générale † Avec le composant JGraph vous pouvez afficher les données sous forme de graphe † Démonstration : www.jgraph.com Un lien « edge » avec du texte Un lien « edge » sans texte Une cellule « cell » avec un couleur et du texte Un groupe « group » qui regroupe 2 cellules et un lien Un port « port » de connexion pour le lien ou point d’attache
  60. 60 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : présentation générale † L’API de JGraph propose de nombreuses caractéristiques † Déplacement, re-dimensionnement et sélection des objets † Agrandissement/Réduction de la vue du graphe † Grille avec modification du pas † Courbe de Bezier et Spline pour les liens, … † Des caractéristiques sont manquantes (présentées dans ce cours) † Aperçu avec positionnement manuel sur le graphe † Impression évoluée avec plusieurs pages † Un composant JGraph doit être ajouté à un container JScollPane et non à un simple JPanel JGraph myGraph = new JGraph(); JScrollPane myScrollPane = new JScrollPane(myGraph); JScrollPane myScrollPane = new JScrollPane(); myScrollPane.add(myGraph); Affiche le JGraph avec des ascenseurs si besoin Le JGraph n’est pas visible dans ce cas là
  61. 61 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † Tout composant dans un JGraph est considéré comme un objet de type GraphCell † Nous distinguons trois types d’objets † Cellule ou groupe (la donnée à afficher ou les objets à regrouper) † Lien (objet graphique qui relie deux cellules) † Port (objet graphique qui sert d’ancre entre une cellule à un lien)
  62. 62 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † Un objet de type GraphCell a également le comportement d’un objet MutableTreeNode et plus spécifiquement de type DefaultMutableTreeNode (utilisé dans JTree) † Utilisation des fonctionnalités de la classe MutableTreeNode † Une cellule peut contenir un sous ensemble de point d’attache (Port) et peut-être un enfant d’un groupe † Un groupe peut avoir comme enfants des cellules, des liens (Edge) et/ou des sous-groupes. Un groupe peut donc être un enfant d’un groupe † Un lien peut-être un enfant d’un groupe † Un point d’attache peut-être un enfant d’une cellule (petit fils d’un groupe) † Les aspects liés aux connexions des liens (quels sont les ports connectés) ne sont pas modélisés par les MutableTreeNode
  63. 63 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † Relation entre un lien et les cellules A et B Une cellule B qui contient un point d’ancrage b Une cellule A qui contient un point d’ancrage a La racine est obligatoirement un groupe Un port contient une référence à son parent (cellule) MutableTreeNode Un port contient également une référence à l’ensemble de liens connectés à ce port HashSet Un lien entre la cellule A et B Une cellule a accès à l’ensemble de ses sous enfants (port) MutableTreeNode Un lien a un accès au référence du port a et du port b
  64. 64 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † La structure proposée par JGraph permet un accès directe aux objets d’un graphe † L’accès à une cellule, un groupe, un lien ou un port donne la possibilité d’extraire n’importe quelle référence d’un objet du graphe † Différentes possibilités d’extraction de référence † Lien : accès aux références du port source et cible et éventuellement du groupe † Port : accès à la référence de la cellule et de l’ensemble des liens † Cellule : accès aux références des ports et éventuellement du groupe † Groupe : accès aux références des cellules et des liens
  65. 65 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † Un groupe ou une cellule doivent être construits à partir d’un objet de type DefaultGraphCell † Outre les méthodes fournies par DefautMutableTreeNode la classe DefaultGraphCell propose uniquement des méthodes pour modifier des attributs des objets (cellule, port et lien) † AttributeMap getAttributes() : retourne les propriétés d’une cellule † setAttributes(AttributeMap attributes) : modifie les attributs † La modification et l’interrogation des attributs propre à JGraph se font différents des autres composants Swing
  66. 66 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † Tous les attributs sont stockés dans un objet de type AttributeMap qui est une table de hachage HashTable † Rappelons que pour accéder à une valeur d’une HashTable il faut y accéder à l’aide d’une clé Clé key1 pour accéder à la valeur val1 † L’ensemble des clés des attributs des objets JGraph sont définies dans la classe GraphConstants † Pour chaque clé un accesseur et un modifieur ont été définies dans la classe GraphConstants
  67. 67 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † Création d’une nouvelle cellule avec association d’un attribut // Création d’une cellule DefaultGraphCell myCell = new DefaultGraphCell(); // Création d’une HashTable pour contenir les attributs. Map myHashTable = new HastTable(); // Modification de l’attribut position et taille myHashTable.put(GraphConstants.BOUNDS, new Rectangle2D.Double(120, 25, 25, 25)); // Même chose en passant par le modifieur GraphConstants.setBounds(map, new Rectangle2D.Double(120, 25, 25, 25)); // Associer les nouveaux attributs (pour l’instant un seul) à la cellule myCell.setAttributes(new AttributeMap(myHashTable)); Préférez l’utilisation des modifieurs et des accesseurs puisqu’elles typent les paramètres et les valeurs de retour
  68. 68 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : gestion des cellules † Modification d’un attribut d’une cellule // Création d’une HashTable pour contenir les attributs. Map myHashTable = myCell.getAttributes(); // Modification de l’attribut Bounds en passant par le modifieur GraphConstants.setBounds(map, new Rectangle2D.Double(120, 25,25,25)); // Associer les nouveaux attributs (pour l’instant un seul) à la cellule myCell.setAttributes(new AttributeMap(myHashTable)); † Interrogation d’un attribut d’une cellule // Création d’une HashTable pour contenir les attributs. Map myHashTable = myCell.getAttributes(); // Même chose en passant le modifieur Rectangle2D myRectangle = GraphConstants.getBounds(map); // Afficher les informations System.out.println(myRectangle.getX()); System.out.println(myRectangle.getY()); System.out.println(myRectangle.getWidth()); System.out.println(myRectangle.getHeight());
  69. 69 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : DefaultPort † La gestion des points d’ancrage est réalisé par un objet de type DefaultPort † Un objet DefaultPort, s’il est associé à une cellule, permet de connaître son objet parent : une cellule † Un objet DefaultPort, s’il est relié à un ou des liens, permet d’accéder aux différents liens † La classe DefaultPort possède plusieurs méthodes † Set getEdges() : retourne les liens associés à ce point d’ancrage † addEdge(Object edge) : curieusement cette méthode ne donne pas l’effet désiré (voir plus loin pour l’ajout de lien)
  70. 70 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : DefaultPort † Exemple : ajout de deux points d’ancrage à une cellule // Création de la cellule DefaultGraphCell myCell = new DefaultGraphCell("Coucou"); // Création des deux ports ou points d’ancrage DefaultPort myFirstPort = new DefaultPort(); DefaultPort mySecondPort = new DefaultPort(); // Ajout des points d’ancrage à la cellule myCell.add(myFirstPort); myCell.add(mySecondPort); L’aspect graphique sera vu dans la suite. On pourra définir la forme et l’emplacement des points d’ancrage
  71. 71 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : DefaultEdge † Les liens entre des cellules sont réalisés par l’intermédiaire d’un objet de type DefaultEdge † Un lien est connecté aux cellules par l’intermédiaire de leur point d’ancrage † L’API de la classe DefaultEdge permet † Object getSource() : le point d’ancrage source † Object getTarget() : le point d’ancrage cible † Il est possible de modifier les caractéristiques d’un lien en modifiant par exemple la forme du trait de liaison † La classe GraphConstants fournit des clés pour modifier la forme du point de départ et d’arrivée
  72. 72 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : DefaultEdge † Exemple : connexion d’un lien à deux cellules // Création de la cellule DefaultGraphCell myCell = new DefaultGraphCell("Coucou"); // Création des deux ports ou points d’ancrage DefaultPort myFirstPort = new DefaultPort(); DefaultPort mySecondPort = new DefaultPort(); // Ajout des points d’ancrage à la cellule myCell.add(myFirstPort); myCell.add(mySecondPort); // Création d’un objet lien DefaultEdge myEdge = new DefaultEdge(); // Associer lien aux points d’ancrage myGraph.getGraphLayoutCache().insertEdge(myEdge, myFirstPort, mySecondPort); Sera vu plus tard dans la partie des vues Création d’un lien entre les points d’ancrage myFirstPort et mySecondPort
  73. 73 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : DefaultEdge † Exemple : modification des attributs d’un lien ... // Création d’un objet lien DefaultEdge myEdge = new DefaultEdge(); // Modification des attributs du lien myHashTable = myEdge.getAttributes(); GraphConstants.setLineBegin(myHashTable, GraphConstants.ARROW_CIRCLE); GraphConstants.setLineEnd(myHashTable, GraphConstants.ARROW_DIAMOND); myEdge.setAttributes(new AttributeMap(myHashTable)); // Ajout du noeud myGraph.getGraphLayoutCache().insertEdge(myEdge, myFirstPort, mySecondPort); Le début et la fin du lien ont été modifié La cellule contient un port qui est centré L’apparence du lien a été modifiée
  74. 74 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : modèle † Un modèle d’un composant JGraph doit implémenter l’interface GraphModel † On utilisera la classe DefaultGraphModel qui propose une implémentation par défaut † Un modèle DefaultGraphModel offre une API pour interroger les entités du graphe † List getRoots() : récupère l’ensemble des objets racines † int getRootCount() : donne le nombre total d’objets racines † Object getRootAt(int index) : récupère l’objet racine à l’indice index † Nombreuses méthodes statiques † …
  75. 75 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : modèle † Exemple : extrait les objets racines du modèle // Création de la cellule DefaultGraphCell myCell = new DefaultGraphCell("Coucou"); // Création des deux ports ou points d’ancrage DefaultPort myFirstPort = new DefaultPort(); DefaultPort mySecondPort = new DefaultPort(); // Ajout des points d’ancrage à la cellule myCell.add(myFirstPort); myCell.add(mySecondPort); // Création d’un objet lien DefaultEdge myEdge = new DefaultEdge(); // Associer lien aux points d’ancrage myGraph.getGraphLayoutCache().insertEdge(myEdge, myFirstPort,mySecondPort); for (int i = 0; i < myGraph.getModel().getRootCount(); i++) { System.out.println(myGraph.getModel().getRootAt(i).getClass()); } Les objets DefaultPort ne sont pas des objets racines du graphe
  76. 76 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † La gestion de la vue sous JGraph est différente des autres composants Swing † Il est possible d’associer pour chaque objet de type GraphCell une vue et par conséquent un « Renderer » et un « Editor » spécifiques † Le composant JTree n’autorise qu’une seule vue et par conséquent un seul « Renderer » et « Editor » † Le composant JTable peut autoriser une vue par colonne ou une vue par type de données † L’ensemble des vues d’un composant JGraph permet d’obtenir la visualisation complète du graphe
  77. 77 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † L’objet de type GraphLayoutCache permet de réaliser la relation ou « mapping » entre le modèle et les vues † La classe GraphLayoutCache fournit également de nombreuses méthodes permettant d’ajouter notamment des cellules, des liens, … † insert(Object cell) : ajoute une cellule dans le graphe † insertEdge(Object edge, Object source, Object target) : ajoute un lien edge aux points d’ancrage source et target † insertGroup(Object group, Object[] children) : ajoute un groupe à partir des sous éléments children
  78. 78 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † L’objet GraphLayoutCache est associé à l’objet JGraph et peut-être récupéré ou créé † GraphLayoutCache JGraph#getGraphLayoutCache() : retourne l’objet GraphLayoutCache contenu dans l’objet JGraph † JGraph#setGraphLayoutCache(GraphLayoutCache p) : modifie l’objet GraphLayoutCache du JGraph † L’intérêt de modifier l’objet de type GraphLayoutCache est de pouvoir changer très rapidement de type de représentation pour un graphe donné Il faut absolument passer par l’objet GraphLayoutCache pour modifier les éléments d’un graphe
  79. 79 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † Exemple : création de cellules et de liens (rappel) ... DefaultGraphCell myFirst = new DefaultGraphCell("Debut"); DefaultGraphCell mySecond = new DefaultGraphCell("Fin"); // Ajoute les cellules dans le modèles et associe deux vues myGraph.getGraphLayoutCache().insert(myFirst); myGraph.getGraphLayoutCache().insert(mySecond); DefaultPort myFirstPort = new DefaultPort(); DefaultPort mySecondPort = new DefaultPort(); // Ajoute les ports aux cellules myFirst.add(myFirstPort); mySecond.add(mySecondPort); DefaultEdge myEdge = new DefaultEdge(); // Ajoute un lien myGraph.getGraphLayoutCache().insert(myEdge, myFirstPort, mySecondPort); Ajout de deux cellules : dans le modèle et deux vues Ajout d’un lien : dans le modèle et une vue
  80. 80 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † Une vue permet de spécifier différents objets et attributs qui caractérisent les aspects graphiques d’un élément (cellule, …) † Objet « Renderer » † Objet « Editor » † Taille, … † Les vues définissent une couche supplémentaire permettant de paramétrer les objets « Renderer » † Toute les vues doivent se comporter comme un objet de type AbstractCellView † Les trois types d’objet d’un graphe ont chacun une classe prédéfinie pour représenter leur vue : † Port : PortView † Lien : EdgeView † Cellule ou groupe : VertexView Le contenu à afficher en terme de composant (JLabel, …) est obtenu par le l’objet renderer
  81. 81 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † Chaque objet de type AbstractCellView possède son propre objet « Renderer » et possède un objet « Editor » commun Association Implémentation Implémentation
  82. 82 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : VertexView † La classe VertexView permet de créer des vues pour les cellules ou les groupes † Différentes méthodes sont définies et doivent être redéfinies pour avoir un comportement spécifique pour une cellule ou un groupe † Rectangle2D getBounds() : retourne la position et la taille de la cellule † … † Exemple : changer la taille d’une cellule public class MyVertexView extends VertexView { public Rectangle2D getBounds() { Rectangle2D temp = super.getBounds(); return new Rectangle2D.Double(temp.getX(), temp.getY(), 100, 100); } ... } La méthode qui permet de déterminer la position et la taille à tout instant Par défaut la taille d’une cellule est ajusté selon le contenu
  83. 83 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : EdgeView † La classe EdgeView permet de créer des vues pour les liens † Différentes méthodes ont été définies pour reflétées l’apparence d’un lien † Point2D getLabelPosition() : modifie l’emplacement du JLabel qui sert à afficher une légende au lien † CellView getSource() : retourne la vue de la cellule source † CellView getTarget() : retourne la vue de la cellule cible † boolean isLoop() : retourne vraie si le lien est une boucle (la source et la cible sont les mêmes) † …
  84. 84 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : EdgeView † Exemple : changer la position du texte d’un lien public class MyEdgeView extends EdgeView { ... public MyEdgeView(Object cell) { super(cell); } public Point2D getLabelPosition() { return new Point2D(10,10); } } Avant : le texte est centré sur la longueur du lien Après : le texte est placé à une position fixe L’origine est situé sur le départ du lien (côté point d’ancrage source) Une autre façon est de modifier la valeur de la clé LABELPOSITION d’un lien
  85. 85 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : EdgeView † Un objet EdgeView permet également de créer sur la longueur dulien des points de cassures † La classe fournit un ensemble de méthodes permettant de manipuler et interroger les points de cassures † addPoint(int ind, Point2D p) : ajoute un nouveau point de cassure † Point2D getPoint(int ind) : retourne le point à l’indice ind † static double getLength(CellView v) : retourne la longueur d’un lien
  86. 86 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : EdgeView † L’ajout de point de cassures de manière interactive se fait à l’aide de la sous classe EdgeView.EdgeHandle † Elle contient des méthodes pour la gestion des événements liés à la souris (mouseDragged, mousePressed, …) † Pour ajouter un objet de manipulation (EdgeHandle) il faut redéfinir la méthode † CellHandle getHandle(GraphContext c) : retourne l’objet permettant de manipuler les points de cassure † Exemple : désactiver la création de points de cassure public CellHandle getHandle(GraphContext context) { return null; }
  87. 87 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : EdgeView † L’API JGraph fournit par défaut deux formes pour les liens † Une forme est composée d’un ensemble de points de cassure disposée suivant une manière précise † Possibilité de fournir explicitement de nouvelles formes en se basant sur l’interface Edge.Routing † int getPreferredLineStyle(EdgeView edge) : style pour le lien † List route(EdgeView edge) : ensemble des points de cassure † La relation entre lien et objet Edge.Routing est faite par la modification de la clé ROUTING Forme appelée ROUTING_SIMPLE Forme appelée ROUTING_DEFAULT
  88. 88 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : EdgeView † Exemple : forcer une forme pour un lien public class MyEdgeRouting extends Edge.Routing { public List route(EdgeView edge) { List newPoints = new ArrayList(); Point2D from, to = ...; double frombisX = from.getX(); double frombisY = from.getY() + 50; double tobisX = to.getX(); double tobisY = frombisY; newPoints[1] = new Point(frombisX, frombisY); newPoints[2] = new Point(tobisX, tobisY); ... } ... // Ajoute les ports aux cellules myFirst.add(myFirstPort); mySecond.add(mySecondPort); DefaultEdge myEdge = new DefaultEdge(); GraphConstants.setRooting(myEdge.getAttributes(), new MyEdgeRouting()); Hauteur constante Largeur et hauteur variables
  89. 89 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : PortView † La classe PortView permet de donner une représentation aux points d’ancrage † Le composant JGraph peut décider d’afficher ou pas les points d’ancrage † JGraph#setPortsVisible(boolean) : affiche ou pas les point d’ancrage † Différentes méthodes ont été définies pour modifier l’apparence d’un point d’ancrage † Point2D getLocation() : cette méthode permet de retourner la position du point d’ancrage † …
  90. 90 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : PortView † Exemple : changer les points d’ancrage d’une cellule public class MyPortView extends PortView { ... public Point2D getLocation(EdgeView edge, Point2D nearest) { CellView vertex = getParentView(); Point2D pos = null; if (vertex != null) { Rectangle2D r = vertex.getBounds(); double highOrLow = 0; if (((DefaultGraphCell)vertex.getCell()).getChildAt(0) == cell) { highOrLow = r.getMinY(); } else { highOrLow = r.getMaxY(); } if (r != null) return new Point2D.Double(r.getCenterX(), highOrLow); } return pos; } } Avant : deux cellules, deux liens et quatre ports sont confondus Après : deux cellules, deux liens et quatre ports séparés
  91. 91 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † La gestion de l’ensemble des vues d’un composant JGraph se fait dans un objet de type CellViewFactory † Une implémentation de l’interface CellViewFactory par défaut existe et s’appelle DefaultCellViewFactory † Un objet CellViewFactory ne fait rien d’autre que d’envoyer les vues suivant les objets concernés † Le regroupement des vues du graphe se fait par l’intermédiaire de † CellView createView(GraphModel myModel, Object cell) : elle permet de retourner une vue par rapport à son objet modèle cell
  92. 92 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † Exemple : associer des nouvelles vues aux éléments d’un JGraph public MyCellViewFactory extends DefaultCellViewFactory { public CellView createView(GraphModel model, Object cell) { if (model.isPort(cell)) { return new MyPortView(cell); } else if (model.isEdge(cell)) { return new MyEdgeView(cell); } else return new MyVertexView(cell); } } Suivant le type d’objet (cellule, lien et port) une vue est proposée Ne pas oublier de transmettre l’objet modèle à la vue Possibilité de définir plus d’une vue par type d’objet (lien, port, …)
  93. 93 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † Pour associer un objet CellViewFactory à l’objet JGraph courant il faut modifier l’objet GraphLayoutCache † GraphLayoutCache#setFactory(CellViewFactory rf) : modifie la gestion courante des vues † Possibilité de changer de CellViewFactory pour donner rapidement un autre type de représentation pour votre graphe † Exemple : association d’un objet CellViewFactory à un JGraph myGraph.getGraphLayoutCache().setFactory(new DefaultCellViewFactory() { public CellView createView(GraphModel model, Object cell) { if (model.isPort(cell)) { return new MyPortView(cell); } else if (model.isEdge(cell)) { ... } ... } }); Pensez à proposer pour tous les types d’objet GraphCell une vue associée
  94. 94 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : vues † Exemple (suite) : associer un CellViewFactory à un JGraph myGraph.getGraphLayoutCache().setFactory(new DefaultCellViewFactory() { public CellView createView(GraphModel model, Object cell) { if (model.isPort(cell)) { return new MyPortView(cell); } ... }}); class MyVertexView extends VertexView { public MyVertexView(Object cell) { super(cell) } public Rectangle2D getBounds() { Rectangle2D temp = super.getBounds(); return new Rectangle2D.Double(temp.getX(), temp.getY(), 100, 100); } } class MyPortView extends PortView { ... } class MyEdgeView extends EdgeView { ... } ... Suivant le type d’objet (cellule, lien et port) on propose une vue associée
  95. 95 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : paramétrage de la vue † Possibilité de paramétrer de manière globale l’apparence d’un objet JGraph et les différents objets qui le composent † Grille † setGridVisible(boolean f) : affiche ou pas la grille † setGridSize(double n) : définit le pas de la grille † setGridEnabled(boolean f) : active ou pas la grille † setGridColor(Color c) : couleur de la grille † Apparence † setAntiAliased(boolean b) : active ou pas l’effet de lissage † setScale(double n) : agrandit ou réduit la taille du graphe Grille visible et activée avec un pas de 6
  96. 96 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : paramétrage de la vue † Edition et manipulation des éléments du graphe † setBendable(boolean b) : active ou pas l’ajout de points de cassure † setConnectable(boolean b) : autorise ou pas la connexion de lien † setEditable(boolean b) : autorise ou pas l’édition (Editor) † setEditClickCount(int count) : définit le nombre de click pour l’édition † setMoveable(boolean f) : autorise le déplacement † setPortsVisible(boolean f) : affiche ou pas les ports de connexion † setSelectionEnabled(boolean f) : active ou pas la sélection † setSizeable(boolean f) : active ou pas le redimensionnement Ces méthodes modifient de façon globales les paramètres des éléments. Il est également possible de modifier les paramètres de manière ponctuelle
  97. 97 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Renderers et Editors † Les objets AbstractCellView permettent de configurer les attributs graphiques des éléments d’un graphe (position, couleur, …) mais ne permettent pas directement de créer un nouveau « contenu » † L’API JGraph permet de paramétrer pour les éléments (cellule, groupe, lien et point d’ancrage) † Le rendu : le composant qui représente graphique un élément du graphe † L’édition : le composant permettant d’éditer des valeurs d’un élément † Un objet « Editor » est appelé quand l’utilisateur effectue une action « d’édition » sur un élément (sous condition que l’élément soit éditable) † Un objet « Renderer » est une vue sans réaction directe qui retourne une visualisation d’un élément
  98. 98 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Renderers et Editors Le « renderer » de la cellule a permis d’afficher un rectangle plein coloré par un dégradé L’« editor » de la cellule a permis d’afficher un JTextField pour l’édition du contenu de la cellule Le « renderer » du lien a permis d’afficher une flèche et le texte à afficher est vide L’« editor » du lien a permis d’afficher un JTextField pour l’édition du contenu du lien
  99. 99 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Renderers † Deux solutions sont envisageables pour modifier l’objet rendu d’une cellule, groupe, lien ou point d’ancrage † Redéfinir la méthode Component getRendererComponent(…) issu directement de la classe mère des vues AbstractCellView † Redéfinir la méthode CellViewRenderer getRenderer(…) définie pour chaque vue † La première solution prend le dessus sur la seconde solution † La seconde est à envisager si vous souhaitez spécialiser les renderers déjà existant : † VertexRenderer : pour les cellules ou les groupes † PortRenderer : pour les points d’ancrages † EdgeRenderer : pour les liens Nous nous limiterons à présenter la première solution
  100. 100 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Renderers † La méthode à redéfinir (dans la cas de la seconde solution) pour modifier le renderer est semblable à celle traitée pour la JTable ou le JTree † Component getRendererComponent(JGraph myGraph, boolean selected, boolean focus, boolean preview) † JGraph mygraph : référence à la vue du graphe † boolean selected : l’élément est-il sélectionné ? † boolean focus : l’élément a-t-il le focus ? † boolean preview : l’élément est-il une preview (pour le fantôme) ? L’accès à l’objet DefaultGraphCell est obtenu par l’attribut protégé cell Dans le cas d’une JTable ou d’un JTree la méthode associée propose en plus un objet « utilisateur »
  101. 101 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Vertex Renderer † Exemple : modifier le renderer d’une cellule private class MyVertexView extends VertexView { public Component getRendererComponent(JGraph graph, boolean selected, boolean focus, boolean preview) { JPanel myVertexPanel = new JPanel(); myVertexPanel.setLayout(new BoxLayout(myVertexPanel, BoxLayout.Y_AXIS)); JLabel myLabelImage = new JLabel(new ImageIcon("image.gif")); myLabelImage.setBorder(defaultBorder); JLabel myLabelName = new JLabel(cell.toString()); JLabel myLabelOrdonnancement = new JLabel(" HELLO "); myLabelOrd.setAlignmentX(Component.CENTER_ALIGNMENT); myLabelOrd.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2)); myVertexPanel.add(myLabelImage); myVertexPanel.add(Box.createRigidArea(new Dimension(0, 15))); myVertexPanel.add(myLabelName); myVertexPanel.add(Box.createRigidArea(new Dimension(0, 15))); myVertexPanel.add(myLabelOrdonnancement); return myVertexPanel; } Redéfinition de la méthode Trois JLabel avec un Border pour le dernier Un JPanel englobant L’objet « utilisateur » est obtenu par l’attribut protégé cell
  102. 102 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Port Renderer † Exemple : modifier le renderer d’un point d’ancrage public class MyPortView extends PortView { public Rectangle2D getBounds() { Rectangle2D myBounds = super.getBounds(); myBounds.setRect(myBounds.getX(), myBounds.getY(),60,60); return myBounds; } public Component getRendererComponent(JGraph graph, boolean selected, boolean focus, boolean preview) { JComponent myCompo = new JComponent() { public void paint(Graphics g) { Dimension d = this.getSize(); g.setColor(Color.BLACK); super.paint(g); g.draw3DRect(0,0,10,10,true); g.drawString(" Port",10,10); } }; return myCompo; } ... } Pour agrandir la taille du Renderer
  103. 103 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Renderers † La seconde solution peut être utilisée pour proposer un renderer spécifique nécessitant l’utilisation de Java2D † Principe de cette solution † Définition d’une nouvelle classe qui hérite directement d’un renderer spécifique (VertexRenderer, EdgeRenderer, PortRenderer) ou qui implémente l’interface CellViewRenderer † Implémentation ou redéfinition des méthodes jugées nécessaires † Exemple : redéfinition de la méthode paint public CellViewRenderer getRenderer() { return new MyVertexRenderer(); } class MyVertexRenderer extends VertexRenderer { public void paint(Graphics g) { super.paint(g); ... } } Redéfinition de la méthode paint(…) Ne redéfinissez pas la méthode getRendererComponent si vous choisissez cette solution Classe interne
  104. 104 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : comportement des vues † Toutes les vues (VertexView, EdgeView et PortView) peuvent définir des comportements locales suite aux réactions de la souris † Les comportements sont définis par l’interface CellHandle † mouseDragged(MouseEvent e) : déplacement avec bouton enfoncé † mouseMoved(MouseEvent e) : déplacement † mousePressed(MouseEvent e) : bouton pressé † mouseReleased(MouseEvent e) : bouton relaché † overlay(Graphics g) : dessin du fantôme † paint(Graphics g) : dessin de l’après † L’association d’un objet CellHandle avec une vue se fait en redéfinissant la méthode † CellHandle getHandle(GraphContext r) : retourne un objet CellHandle où r permet de connaître l’objet JGraph, …
  105. 105 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : comportement des vues † Les vues définissent par défaut des comportements † VertexView : pour le redimensionnement d’une cellule † EdgeView : pour le déplacement d’un lien à un port † PortView : aucun † Dans quel cas a-t-on besoin de redéfinir le CellHandle d’une vue † Pour une cellule, réagir aux actions d’un click à une position donnée de la souris (voir figure) † Pour une cellule, faire apparaître des informations supplémentaire suite au déplacement du curseur † Pour un lien, afficher des informations supplémentaires suite au déplacement du curseur Le CellHandle est la seule solution pour interagir sur les vues. Rappelons que les renderers sont des vues sans réaction Besoin d’un CellHandle pour agir sur ce bouton
  106. 106 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Editors † Un « Editor » doit implémenter l’interface GraphCellEditor qui hérite également de l’interface CellEditor utilisée par tous les objets ayant un « Editor » : JTree, JTable, … † Cette interface possède entre autre une méthode qui retourne le composant à afficher pour l’édition † Component getGraphCellEditorComponent(JTable graph, Object value, boolean isSelected) † JGraph graph : référence du graph associé à l’« Editor » † Object value : valeur de l’élément (un objet de type GraphCell qui est en fait un objet MutableTreeNode) † boolean isSelected : l’élément (groupe, cellule, lien ou port) est-il sélectionné † Pour éviter d’implémenter toutes les méthodes de l’interface CellEditor vous pouvez utiliser la classe AbstractCellEditor
  107. 107 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Editors † Si la classe AbstractCellEditor est utilisée en place de CellEditor certaines méthodes ont un comportement prédéfini † stopCellEditing() : déclenche l’arrêt de l’« Editor » † cancelCellEditing() : déclenche l’annulation de l’« Editor » † addCellEditorListener(CellEditorListener) : ajoute un « écouteur » † Cependant vous devrez fournir obligatoirement une implémentation de la méthode † Object getCellEditorValue() : retourne la valeur que l’utilisateur vient de saisir (la méthode setUserObject(…) de l’élément GraphCell est alors appelée) † Principe de codage † Implémentez getGraphCellEditorComponent(…) pour retourner le composant d’édition † La validation du composant d’édition doit appeler stopCellEditing() † Implémentez getCellEditorValue()
  108. 108 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Vertex Editor † Exemple : modifier l’editor d’une cellule public class MyAbstractCellEditor extends AbstractCellEditor implements GraphCellEditor { private JPanel myPanel; private JTextField myTextField; public MyAbstractCellEditor() { myPanel = new JPanel(); myTextField = new JTextField(); myPanel.setLayout(new BorderLayout()); myPanel.add(BorderLayout.NORTH, new JLabel("Mon Editor")); myPanel.add(BorderLayout.CENTER,myTextField); myTextField.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { MyAbstractCellEditor.this.stopCellEditing(); }}); } public Component getGraphCellEditorComponent(JGraph gra, Object value, boolean isSelected) { myTextField.setText((String)((DefaultGraphCell)value).getUserObject()); return myPanel; } public Object getCellEditorValue() { L’Editor est compoé d’un JLabel et d’un JTextField L’objet transmis à l’Editor est un objet GraphCell
  109. 109 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : Edge Editor † Exemple : modifier l’editor d’un lien public class MyAbstractEdgeCellEditor extends AbstractCellEditor implements GraphCellEditor { private JComboBox myCombo; private String[] myTab = {"Action", "Réaction", "Transition"}; public MyAbstractEdgeCellEditor() { myCombo = new JComboBox(myTab); myCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { MyAbstractEdgeCellEditor.this.stopCellEditing(); } }); } public Component getGraphCellEditorComponent(JGraph graph, Object value, boolean isSelected) { myCombo.setSelectedItem((DefaultEdge)value); return myCombo; } public Object getCellEditorValue() { return myCombo.getSelectedItem(); }} L’objet transmis à l’Editor est un objet GraphCell et plus précisément un DefaultEdge
  110. 110 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : modèle de sélection † Le modèle de sélection gère les aspects liés à la sélection d’un élément d’un graphe (un lien, une cellule ou un groupe) † Un modèle de sélection doit implémenter l’interface appelée GraphSelectionModel † Possibilité de modifier un modèle de sélection pour tous les éléments d’un composant JGraph † setSelectionModel(GraphSelectionModel) : modifie le modèle de sélection † GraphSelectionModel getSelectionModel() : récupère le modèle de sélection † Pour écouter le changement de sélection d’un élément † JGraph#addGraphSelectionListener(GraphSelectionListener) : ajoute un écouteur de sélection Certaines méthodes liées à la sélection sont disponibles à la fois par le modèle de sélection ou par l’objet JGraph
  111. 111 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : modèle de sélection † La définition explicite du modèle de sélection n’est utile que si effectuer des traitements pointus sur les sélections † Pour le reste des aspects liés à la sélection utilisez les méthodes de la classe JGraph qui pointent directement sur le modèle de sélection † Curieusement certaines méthodes ne sont pas disponibles comme l’étaient des méthodes de JTable ou JTree † GraphSelectionModel#setSelectionMode(int) : choix du modèle de sélection † MULTIPLE_GRAPH_SELECTION : plusieurs éléments † SINGLE_GRAPH_SELECTION : un seul élément † Object JGraph#getSelectionCell() : premier élément sélectionné † Object[] JGraph#getSelectionCells() : éléments sélectionnés † clearSelection() : supprime les sélections
  112. 112 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : modèle de sélection † Deux modes différents de sélection Mode de sélection à SINGLE_GRAPH_SELECTION Mode de sélection à MULTIPLE_GRAPH_SELECTION Seul le lien du bas n’est pas sélectionné
  113. 113 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : modèle de sélection † Exemple : accès aux informations de la sélection courante myGraph.addGraphSelectionListener(new GraphSelectionListener() { public void valueChanged(GraphSelectionEvent selEvent) { Object[] list = myGraph.getSelectionCells(); for (int i = 0; i < list.length; i++) { if (list[i] instanceof DefaultEdge) { System.out.println("Un Lien"); } else if (list[i] instanceof DefaultGraphCell) { System.out.println("Une cellule ou groupe"); } } } });
  114. 114 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Possibilité dans un JGraph d’ajouter dynamiquement des cellules et des liens † L’ajout des éléments se fait à partir de l’objet GraphLayoutCache qui s’occupe du « Mapping » entre le modèle et les vues † insert(Object cell) : ajoute un élément cell † insertEdge(Object edge, Object source, Object target) : ajoute un lien edge connecté à un port source et target † remove(Object[] cells) : supprime les objets cells † L’ajout d’une cellule nécessite uniquement un point de création † L’ajout d’un lien nécessite un port de départ et un port d’arrivée d’une ou plusieurs cellules
  115. 115 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † L’objet JGraph est associé à un objet de type BasicMarqueeHandle permettant de réaliser des actions sur l’ensemble des vues † A la différences des objets CellHandle associées à un type de vue l’objet BasicMarqueeHandle permet de faire des traitements sur tous types de vues † boolean isForceMarqueeEvent(MouseEvent e) : si true désactive le déplacement et l’objet CellHandle de l’élément associé † mouseMoved(…), mousePressed(…), … : les méthodes qui traitent les actions de la souris † L’association d’un objet BasicMarqueeHandle à un objet JGraph se fait par l’intermédiaire † JGraph#setMarqueeHandler(BasicMarqueeHandler basic) : associer basic à une référence JGraph
  116. 116 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Exemple : application finale avec de la manipulation directe … Des boutons de contrôle « Annuler », « Ajouter », « Supprimer » Composant JGraph Objet DefaultGraphCell incluant un objet DefaultPort On profitera de cet exemple pour résumer les parties précédentes et on montrera certaines méthodes non étudiées
  117. 117 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Exemple (suite) : code de la partie graphique de l’application public class DynamicGraph extends JFrame { private int stateAppl = 0; public DynamicGraph() { super("SimpleGraph"); myGraph = new JGraph(new DefaultGraphModel()); myGraph.setMarqueeHandler(new MyMarqueeHandler()); JScrollPane myScrollPane = JScrollPane(myGraph); getContentPane().add(myScrollPane); JPanel myPanel = new JPanel(); noCell = new JToggleButton("Annuler"); noCell.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { stateAppl = 0; } }); addCell = new JToggleButton("Ajouter"); removeCell = new JToggleButton("Supprimer"); myPanel.add(noCell); getContentPane().add(myPanel, BorderLayout.SOUTH); ... } class MyMarqueeHandler extends BasicMarqueeHandler { ... Construction graphique de l’interface Abonnement des composants sources L’objet BasicMarqueeHandler pour la manipulation des vues
  118. 118 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Exemple : ajouter dynamiquement une cellule public void mousePressed(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { if (stateAppl == 1) { DefaultGraphCell myFirst = new DefaultGraphCell("Cellule 1"); DefaultPort myPort1 = new DefaultPort(); myFirst.add(myPort1); Map myHashTable = new Hashtable(); GraphConstants.setBounds(myHashTable, new Rectangle2D.Double(e.getX(),e.getY(),40,100)); myFirst.setAttributes(new AttributeMap(myHashTable)); myGraph.getGraphLayoutCache().insert(myFirst); noCell.setSelected(true); stateAppl = 0; } } ... } Cette méthode sera également utilisée pour la construction dynamique d’un lien Construction d’une cellule Modification de la position Ajout dans le composant JGraph
  119. 119 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Exemple : ajouter dynamiquement un lien (mousePressed) class MyMarqueeHandler extends BasicMarqueeHandler { protected Point2D start, current; protected PortView port, firstPort; public boolean isForceMarqueeEvent(MouseEvent e) { port = getSourcePortAt(e.getPoint()); if (port != null && myGraph.isPortsVisible()) return true; return super.isForceMarqueeEvent(e); } public void mousePressed(MouseEvent e) { ... if (port != null && myGraph.isPortsVisible()) { start = myGraph.toScreen(port.getLocation()); firstPort = port; } else { super.mousePressed(e); } } Le reste sur le transparent précédent Tente d’extraire l’objet PortView suivant la position du curseur
  120. 120 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Exemple : ajouter dynamiquement un lien (mouseDragged) public void mouseDragged(MouseEvent e) { if (start != null) { Graphics g = myGraph.getGraphics(); PortView newPort = getTargetPortAt(e.getPoint()); if (newPort == null || newPort != port) { paintConnector(Color.black, myGraph.getBackground(), g); port = newPort; if (port != null) current = myGraph.toScreen(port.getLocation()); else current = myGraph.snap(e.getPoint()); paintConnector(myGraph.getBackground(), Color.black, g); } } super.mouseDragged(e); } Pendant le déplacement de la souris on dessine le trait
  121. 121 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Exemple : ajouter dynamiquement un lien (mouseReleased) public void mouseReleased(MouseEvent e) { if (e != null && port != null && firstPort != null && firstPort != port) { DefaultEdge myEdge = new DefaultEdge(); myGraph.getGraphLayoutCache().insertEdge(myEdge, (DefaultPort)firstPort.getCell(), (DefaultPort)port.getCell()); e.consume(); } else { myGraph.repaint(); } firstPort = port = null; start = current = null; super.mouseReleased(e); } PortView getSourcePortAt(Point2D point) // Extrait un PortView le plus proche de point PortView getTargetPortAt(Point2D point) // Extrait un PortView pour l’arrivée paintConnector(Color fg, Color bg, Graphics g) // Dessine les traits ...
  122. 122 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : ajout et suppression dynamique † Exemple : supprimer dynamiquement un lien ou une cellule public DynamicGraph() { ... JButton removeCell = new JButton("Supprimer"); removeCell.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Object[] t = myGraph.getSelectionCells(); t = myGraph.getDescendants(t); myGraph.getGraphLayoutCache().remove(t); } }); ... Cette méthode permet de récupérer tous les sous objets On reprend l’implémentation du constructeur
  123. 123 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    JGraph : bilan † Un composant JGraph est une vue paramétrable qui permet d’afficher et modifier des données d’un graphe JGraph GraphModel 1 GraphSelectionModel 1 Données du composant Sélection des données GraphModelListener 0..n GraphSelectionListener 0..n Avertir que le modèle a changé Ecouteur pour avertir que la sélection a changé GraphLayoutCache Mapping entre modèle et vue 1 CellViewFactory 1 VertexView EdgeView PortView Dispatching des vues Vue GraphCellEditor 1 1 Ecouteur pour avertir que l’édition est annulée ou validée CellHandle VertexRenderer EdgeRenderer PortRenderer Renderer Paramétrage de l’affichage des données 1 BasicMarqueeHandler 1
  124. 124 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : autres techniques … † Les composants de visualisation d’informations ont parfois besoin de techniques supplémentaires pour manipuler les données † Agrandissement (une table, un graphe, …) † Exportation dans un format d’image (EPS, BMP, JPG, …) † Représentation sous différentes vues (courbe, camembert, …) † Impression sur une ou plusieurs pages † Certaines techniques sont directement implémentées par une API Java (java.awt.print) † D’autres nécessitent au contraire l’utilisation de l’API Java 2D afin de permettre d’effectuer des traitements graphiques évolués † Exemple : l’API pour l’impression
  125. 125 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : impression † Le processus d’impression est l’ensemble des taches que réalise un programme pour envoyer des données vers une imprimante † Indiquer au système d’impression quels objets de l’application sont à imprimer † Indiquer au système les données concernant l’impression : nombre de pages, format de page, … † Appeler la fonction d’impression pour imprimer les objets à partir du gestionnaire d’impression (PrinterJob) Boîte de dialogue pour la gestion de l’impression définie par le système
  126. 126 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : Printable † Les composants Swing possèdent déjà un comportement pour l’impression mais se limitent pour la plupart à l’impression de texte † Pour être imprimable un objet doit implémenter l’interface Printable † int print(Graphics g, PageFormat pf, int pi) : méthode appelée pour effectuer le rendu sur l’imprimante † g une référence au contexte graphique † pf permet de connaître le taille du papier, ses marges, son orientation, … † pi numéro de page à imprimer † PAGE_EXISTS : indique au gestionnaire d’impression qu’il peut imprimer la page traitée dans print et qu’il pourra rappeler de nouveau print † NO_SUCH_PAGE : indique au gestionnaire d’impression qu’il n’a plus de page à imprimer et qu’il ne pourra pas rappeler print
  127. 127 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : Printable † Exemple : imprimer un contenu défini dans print public class HelloWorldPrintExample implements Printable { public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException { if (pageIndex !=0) return NO_SUCH_PAGE; Graphics2D g2 = (Graphics2D)g; g2.setFont(new Font("Serif", Font.PLAIN,36)); g2.setPaint(Color.BLACK); g2.drawString("Hello Every Body", 144,144); return PAGE_EXISTS; } } Appeler suite à la première page mais en avertissant le gestionnaire d’impression qu’il ne pourra plus rappeler print Appeler au tout début de l’impression et indique au gestion d’impression qu’il peut imprimer cette page et qu’il pourra rappeler print Impression en PDF
  128. 128 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : Printable † Exemple : imprimer un contenu défini à l’extérieur de print public class CompPrintExample extends JFrame implements Printable { public ComponentsPrintExample() { this.setTitle("Un simple fenêtre"); JButton myButton = new JButton("Coucou"); JTextArea myText = new JTextArea(); myText.setLineWrap(true); myText.setText("Bonjour à tout le monde, un simple ..."); this.getContentPane().add(BorderLayout.CENTER, myText); this.getContentPane().add(BorderLayout.SOUTH,myButton); this.pack(); this.setVisible(true); } public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException { if (pageIndex !=0) return NO_SUCH_PAGE; Graphics2D g2 = (Graphics2D)g; g2.translate(50,50); this.paint(g2); return PAGE_EXISTS; } } Transfert le graphique d’impression au composant
  129. 129 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : format de page † La classe PageFormat décrit les caractéristiques dimensionnelle d’une feuille de papier et son orientation † Une feuille est définie par sa dimension (taille de la feuille), une zone imprimable et une orientation † Les modifications des caractéristiques sont réalisées au travers de la boîte de dialogue qui gère la mise en page (voir transparent suivant) x y Portrait x y Landscape Zone imprimable
  130. 130 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : format de page † La classe PageFormat offre de nombreuses méthodes et constantes † int PORTRAIT : page en mode portrait † int LANDSCAPE : page en mode paysage † int REVERSE_LANDSCAPE : page en mode inverse paysage † int getOrientation() : retourne la valeur de l’orientation (à comparer avec les constantes de PageFormat) † double getWidth() : largeur de la page (A4 : 29,7 cm) † double getHeight() : hauteur de la page (A4 : 21 cm) † double getImageableX() : position en abscisse de la page † double getImageableY() : position en ordonnée de la page † double getImageableWidth() : largeur de la zone imprimable † double getImageableHeight() : hauteur de la zone imprimable
  131. 131 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : format de page † Exemple : imprimer suivant les caractéristiques de la page public class PageFormatPrintExample implements Printable { public int print(Graphics g, PageFormat pf, int pageIndex) { if (pageIndex !=0) return NO_SUCH_PAGE; Graphics2D g2 = (Graphics2D)g; Rectangle2D outline = new Rectangle2D.Double( pf.getImageableX(), pf.getImageableY(), pf.getImageableWidth(), pf.getImageableHeight()); g2.setPaint(Color.black); g2.draw(outline); return PAGE_EXISTS; } Manipulation de la Zone imprimable
  132. 132 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : gestion d’impression † Le gestionnaire d’impression permet de contrôler le processus complet pour l’impression de page † Monter le dialogue d’impression † Montrer le dialogue de mise en page † Débuter et annuler une impression † Le gestionnaire d’impression est géré par un objet PrinterJob † static PrinterJob getPrinterJob() : retourne l’instance du gestionnaire d’impression † setPrintable(Printable printer) : indique l’objet à imprimer † setPrintable(Printable printer, PageFormat pf) : en donnant un format de page † print() : lance l’impression † setJobName(String jn) : modifie le nom du gestionnaire d’impression † getJobName() : retourne le nom du gestionnaire d’impression † PageFormat defaultPage() : retourne l’objet PageFormat par défaut
  133. 133 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : gestion d’impression † Exemple : gestion d’impression en action public class MyPrintDialog extends JFrame { public MyPrintDialog() { ... PrinterJob pj = PrinterJob.getPrinterJob(); pj.setPrintable(new PageFormatPrintExample()); if (pj.printDialog()) { try { pj.print(); }catch(PrinterException e) { System.out.println(e); } } } } L’objet à imprimer et qui doit respecter l’interface Printable Le format de page est celui défini par défaut par le gestionnaire d’impression
  134. 134 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : configurat. de l’impression † Le gestionnaire d’impression permet de faire appel à des interfaces graphiques du système permettant la gestion de la mise en page et de l’impression † boolean PrinterJob#printDialog() : appel la boîte de dialogue pour configurer l’impression † PageFormat PrinterJob#pageDialog(PageFormat page) : appel la boîte de dialogue pour la mise en page où page est le format par défaut Boite de dialogue pour la mise en page Boite de dialogue pour la configuration de l’impression
  135. 135 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Visualisation d’informations : configurat. de l’impression † Exemple : configuration de l’impression en action public class MyPrintDialog extends JFrame { private PageFormat pf; private PrinterJob pj; public MyPrintDialog() { ... PrinterJob pj = PrinterJob.getPrinterJob(); pf = pj.defaultPage(); } public goLayoutAndPrintPage() { pj.pageDialog(pf); pj.setPrintable(new PageFormatPrintExample(),pf); if (pj.printDialog()) { try { pj.print(); }catch(PrinterException e) { System.out.println(e); } } } } L’objet à imprimer à qui est associé le format de page Rien ne vous interdit de proposer des interfaces personnalisées pour la mise en page et la configuration de l’impression
  136. 136 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    † En manipulant NO_SUCH_PAGE et PAGE_EXISTS possibilité d’imprimer plusieurs pages avec un seul PageFormat pour toutes les pages du processus d’impression † La classe Book (java.awt.print.Book) offre la possibilité d’imprimer plusieurs pages avec différents PageFormat † append(Printable p, PageFormat pf) : associe un objet à imprimer p à un objet PageFormat pf † Exemple : impression avec différents formats de pages Visualisation d’informations : multi-pages avancés Book myBook = new Book(); pfPortrait.setOrientation(PageFormat.PORTRAIT); myBook.append(myObject, pfPortrait); pfLandscape.setOrientation(PageFormat.LANDSCAPE); myBook.append(mySecondObject,pfLandscape); PrinterJob.getPrinterJob().setPageable(myBook); Ajout dans l’objet Book des objets à imprimer (peut-être le même) avec des PageFormat différent Une méthode supplémentaire dans PrinterJob pour gérer les objets Pageable
  137. 137 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Autres composants pour la visualisation d’informations † Le composant JFreeCharts permet de représenter des données dans un diagramme † Différentes représentations du diagramme sont proposées † Courbe 2D ou 3D † Bar horizontale ou verticale † Nuage de points † Camembert, … † JFreeCharts permet également l’agrandissement, l’impression, l’exportation sous différents formats † Cette API peut être utilisée dans les clients lourds, riches et légers (Servlets ou JSP) † API gratuite et utilisable dans les applications commerciales † Site et démos : www.jfree.org/jfreecharts
  138. 138 Java Visu - M. Baron - Page keulkeul.blogspot.com @mickaelbaron

    Autres composants pour la visualisation d’informations