C. Recanati
InHM 
Master M1, 2009

Eléments de correction des TP 9 et 10

//  Constants.java

import java.awt.*;

public interface Constants {

    // Les types d'elements
    int LIGNE = 101;
    int RECTANGLE = 102;
    int CERCLE = 103;
    int COURBE = 104;
    
    // Les conditions initiales
    int DEFAULT_ELEMENT_TYPE = RECTANGLE;
    Color DEFAULT_ELEMENT_COLOR = Color.green;
}

// SketcherFrame.java version 1

import java.awt.*;
import java.awt.event.*;
import javax.swing.* ;

public class SketcherFrame extends JFrame 
                      implements Constants {
// membres                     
	protected JTextArea output;	
	protected JScrollPane scrollPane ;
	private JMenuBar menuBar;	

	// couleur et type de l'element courant  
	private Color elementColor 
					= DEFAULT_ELEMENT_COLOR;     	private int elementType = DEFAULT_ELEMENT_TYPE;

	protected String newline = "\n";

// constructeurs
	public SketcherFrame(String titre) {

		// pour definir les menus
		JMenu menu, submenu;
		JMenuItem menuItem;
		JRadioButtonMenuItem rbMenuItem;
		JCheckBoxMenuItem cbMenuItem;

		setTitle(titre);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

        
		// Créer l’éditeur de texte scrollé
		output = new JTextArea(10, 80);
		output.setEditable(false);
		scrollPane = new JScrollPane(output);

		//l’ajouter au cadre
		Container contentPane = getContentPane();
		contentPane.add(scrollPane,
					 BorderLayout.CENTER) ;

		//Créer la barre de menu
		menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		//Construire le premier menu.
		menu = new JMenu("Fichiers");
		menu.setMnemonic(KeyEvent.VK_F);
		menuBar.add(menu);

        //un groupe de JMenuItems pour ce menu
		menuItem = new JMenuItem("Ouvrir",
                                 KeyEvent.VK_O);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(
                					KeyEvent.VK_1, 
						ActionEvent.ALT_MASK));
		menu.add(menuItem);

		menuItem = new JMenuItem("texte et icone", 
                          new      
					 ImageIcon("icone.gif"));
		menuItem.setMnemonic(KeyEvent.VK_A);
		menu.add(menuItem);

		menuItem = … etc …

		menu.addSeparator();
		… etc …

        // Construire le second menu
		menu = new JMenu("Elements");
		… ibid que précédemment avec le menu Fichiers
		menuBar.add(menu);

        //un groupe d’items type radio button 
		ButtonGroup group = new ButtonGroup();
		rbMenuItem = new JRadioButtonMenuItem
					("Ligne", elementType ==LIGNE);
		rbMenuItem.setMnemonic(KeyEvent.VK_L);
		group.add(rbMenuItem);
		rbMenuItem.addActionListener
					(new TypeListener(LIGNE));
		menu.add(rbMenuItem);

		// rebelotte avec le type suivant
		rbMenuItem = new JRadioButtonMenuItem
				("Rectangle", 
					elementType == RECTANGLE);
		…
		rbMenuItem.addActionListener
					(new TypeListener(RECTANGLE));
		…
		menu.addSeparator();

		// le sous menu pour les couleurs
		submenu = new JMenu("Couleur");
		submenu.setMnemonic(KeyEvent.VK_C);
		// un groupe de check box menu items
		ButtonGroup group2 = new ButtonGroup();
		cbMenuItem = new JCheckBoxMenuItem("Rouge",
				elementColor.equals(Color.red));
		cbMenuItem.setMnemonic(KeyEvent.VK_R);
		group2.add(cbMenuItem);
		cbMenuItem.addActionListener (new 
						ColorListener(Color.red));
		submenu.add(cbMenuItem);

		cbMenuItem = new JCheckBoxMenuItem("Bleu",
				 elementColor.equals(Color.blue));
		// … etc …
        
         //Construire le dernier menu.
		menu = new JMenu("Aide");
		menu.setMnemonic(KeyEvent.VK_A);
		
		// ajouter un separateur horizontal avant
		menuBar.add(Box.createHorizontalGlue());
		menuBar.add(menu);
    
	}

	class TypeListener implements ActionListener {
		private int type;	// un type d’element         
		TypeListener(int type) {
			this.type = type;
		}
        
		public void actionPerformed(ActionEvent e) {
			elementType = type;
            
			JMenuItem source =
						 (JMenuItem)(e.getSource());
			String s = "ActionEvent detecte" 
					+" dans TypeListener" + newline
					+ "    Event source: " 
					+ source.getText()
					+ " (une instance de " 
					+ getClassName(source) + ")";
			output.append(s + newline);
		}
	}

	class ColorListener implements ActionListener {
		private Color color;	// couleur d’element 
        
		ColorListener(Color color) {
            // memoriser la couleur
			…
		}
        
		public void actionPerformed(ActionEvent e) {
        
            elementColor = color;
            
            JMenuItem source = 				
					(JMenuItem)(e.getSource());
            String s = "ActionEvent detecte"
				+ " dans ColorListener." + newline
                   …  etc … + getClassName (…) + …
        }
	}

	protected String getClassName(Object o) {
		String classString = o.getClass().getName();
		int dotIndex = classString.lastIndexOf(".");
		return classString.substring(dotIndex+1);
    }

}

//  Sketcher.java 
//  

import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Sketcher {
//	private SketcherModel model;
	private SketcherView view;
	private static SketcherFrame window;
	private static Sketcher  theApp; 
	
	public static void main(String[] args) {
		theApp = new Sketcher();
		theApp.init();
	}
	public SketcherFrame getWindow() {
		return window;
	}
/*	public SketcherModel getModel() {
		return model;
	}
*/	public SketcherView getView() {
		return view;
	}
	public void init() {
		window = new SketcherFrame("Dessin", this);
		Toolkit leKit = window.getToolkit();
		Dimension wndSize = leKit.getScreenSize();
		window.setBounds(wndSize.width/4,
					 wndSize.height/4, wndSize.width/2,
					 wndSize.height/2);

//		model = new SketcherModel();
		view = new SketcherView(this);
//		model.addObserver((Observer)view);
		window.getContentPane().add(view,
							 BorderLayout.CENTER);
		window.setVisible(true);
	}
}

//
// SketcherView.java
//
class SketcherView extends JPanel implements Observer, Constants {
	private Sketcher theApp;			// Objet Application

	public SketcherView(Sketcher theApp) {
		this.theApp = theApp;	// permettra d’accéder au modèle

		// mettre un fond blanc au panneau
		// créer un MouseHandler (défini plus loin) et l’enregistrer
	}
	public void update(Observable o, Object rectangle) {
		// code correspondant aux modifs du modèle
		// rectangle est ici l’objet passé à notifyObservers
                if (rectangle == null)
                    repaint();
                else repaint( (Rectangle) rectangle);
	}
        	public void paintComponent(Graphics g) {
            	super.paintComponent(g); 
            	// récupérer l’iterateur de la LinkedList des éléments 
Iterator elements = …
            
            	while (elements.hasNext()) {
 			Element element = (Element) elements.next();
                		// dessiner l’élément dans sa couleur
			// (utiliser draw de Graphics2D)
            	}
        	}
        
	class MouseHandler extends MouseInputAdapter {
		private Point debut;	// position de la souris au clic
		private Point dernier;	// position de la souris en drag
		private Element tempElement ; // l'element temporaire
		private Graphics2D g2D;	// le contexte graphique 
                        public void mousePressed (MouseEvent e) {
                		// récupérer le point de debut                
 	    		// initialiser g2D en mode XOR pour basculer
			// entre la couleur courante et le blanc
	}
            
            	public void mouseDragged (MouseEvent e) {
               		 // récupérer le dernier point
               		 if (tempElement == null) {
                    			// créer un élément temporaire
                		}
                		else { 
                    			// effacer le precedent
 				// modifier l'element temporaire
                		}
 	   			// dessiner l’élément temporaire
            	}
            
            	public void mouseReleased (MouseEvent e) {
               		 if (tempElement != null) 
                   			 // ajouter l’élément temporaire au modèle
               		 if (g2D != null) {
                    			g2D.dispose();
                		}
                		// remettre tous les membres du MouseHandler à null
            	}
	}
}

Pour terminer l’architecture Modèle/Vue :

//
//  SketcherModel.java 
//  

import java.util.*;

class SketcherModel extends Observable {
	protected LinkedList ListeElements 
= new LinkedList();
        
        public boolean remove(Element element) {
            boolean removed 
= ListeElements.remove(element);
            if (removed) {
                // notifier les vues
            }
            return removed;
        }
        
        public void add(Element element) {
            ListeElements.add(element);
            setChanged();
            notifyObservers(element.getBounds());
        }
        
        public Iterator getIterator() {
            // retourner l’iterateur sur la liste
        }
}

//
//  nouveau SketcherView.java
//  

import javax.swing.*;
import javax.swing.event.*; 	
import java.util.*;			// pour Observer
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;

class SketcherView extends JPanel 
implements Observer,
									 Constants {
	private Sketcher theApp;	// Objet Application

	public SketcherView(Sketcher theApp) {
		this.theApp = theApp;

          setBackground(Color.white);
          setOpaque(true);
    
		MouseHandler handler = new MouseHandler();
		addMouseListener(handler);
		addMouseMotionListener(handler);

	}
	public void update(Observable o, 
Object rectangle) {
		// code correspondant aux modifs du modèle
                if (rectangle == null)
                    repaint();
                else repaint( (Rectangle) rectangle);
	}
	public void paintComponent(Graphics g) {
		super.paintComponent(g); 
            
		Graphics2D g2D = (Graphics2D) g;
		Iterator elems = 
					theApp.getModel().getIterator();
		Element element;
            
		while (elems.hasNext()) {
			element = (Element) elems.next();
			g2D.setPaint(element.getColor());
			g2D.draw(element.getShape());
		}
	}
        
	class MouseHandler extends MouseInputAdapter {
		private Point debut;	// position au clic
		private Point dernier;// position en drag
		private Element tempElement ; // temporaire
		
		private Graphics2D g2D;	

		public void mousePressed (MouseEvent e) {
			System.out.println("clic");

			debut = e.getPoint();                
			g2D = (Graphics2D) getGraphics();
			g2D.setPaint
				(theApp.getWindow().getElementColor());
			g2D.setXORMode(Color.white);
		}
            
		public void mouseDragged (MouseEvent e) {
			System.out.println("drag");

			dernier = e.getPoint();
			if (tempElement == null)
				tempElement = createElement 
							(debut, dernier) ;
			else {
                    // effacer tempElement 
// (le precedent)
                    // le modifier (-> nouveau)
  			}
			// dessiner tempElement (le nouveau)
		}
            
		public void mouseReleased (MouseEvent e) {
			System.out.println("relacher");

                if (tempElement != null) {
//                  theApp.getModel().add(tempElement);
				tempElement = null;
                }
                if (g2D != null) {
                    g2D.dispose();
                    g2D = null;
                }
                debut = dernier = null;	
		}
            
		private Element createElement
						(Point debut, Point fin) {
			switch(theApp.getWindow().getElementType()) {
				case LIGNE: return new …
				case RECTANGLE: return new 
					Element.Rectangle(debut, fin,…
				case CERCLE: …
			}
			return null;
		}
	}
}

// SketcherFrame.java   version 2
//

import java.awt.*;
import java.awt.event.*;
import javax.swing.* ;

public class SketcherFrame extends JFrame implements
									 Constants {
	private Sketcher theApp;	// l'objet Application	
	private JMenuBar menuBar; // la barre de menu
    
	// le type et la couleur d’element par defaut
	private Color elementColor 
= DEFAULT_ELEMENT_COLOR;    	
private int elementType = DEFAULT_ELEMENT_TYPE;

	public SketcherFrame
(String titre, Sketcher theApp) {

		JMenu menu, submenu; // pour les menus
		JMenuItem menuItem;
		JRadioButtonMenuItem rbMenuItem;
		JCheckBoxMenuItem cbMenuItem;

		setTitle(titre);
		this.theApp = theApp;
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		//Créer la barre de menu
		menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		//Construire le premier menu.
		menu = new JMenu("Fichiers");
		menu.setMnemonic(KeyEvent.VK_F);
		menuBar.add(menu) ;
        
		// Construire le second menu
		menu = new JMenu("Elements");
		menu.setMnemonic(KeyEvent.VK_E);         
		menuBar.add(menu);

		//un groupe de radio button menu items
		ButtonGroup group = new ButtonGroup();
		rbMenuItem = 
new JRadioButtonMenuItem("Ligne",
							 elementType == LIGNE);
		rbMenuItem.setMnemonic(KeyEvent.VK_L);
		group.add(rbMenuItem);
		rbMenuItem.addActionListener
					(new TypeListener(LIGNE));
		menu.add(rbMenuItem);

		rbMenuItem = 
new JRadioButtonMenuItem("Rectangle",
						 elementType == RECTANGLE);
		rbMenuItem.setMnemonic(KeyEvent.VK_R);
		group.add(rbMenuItem);
		rbMenuItem.addActionListener
					(new TypeListener(RECTANGLE));
		menu.add(rbMenuItem);

		// rbMenuItem = … etc
// un separateur
		menu.addSeparator();

		// un sous menu
		submenu = new JMenu("Couleur");
		submenu.setMnemonic(KeyEvent.VK_C);

		// un groupe de check box menu items
		ButtonGroup group2 = new ButtonGroup();
		cbMenuItem = new JCheckBoxMenuItem("Rouge",
elementColor.equals(Color.red));
		cbMenuItem.setMnemonic(KeyEvent.VK_R);
		group2.add(cbMenuItem);
		cbMenuItem.addActionListener
					(new ColorListener(Color.red));
		submenu.add(cbMenuItem);

		cbMenuItem = new JCheckBoxMenuItem("Bleu",
				elementColor.equals(Color.blue));
		cbMenuItem.setMnemonic(KeyEvent.VK_B);
		group2.add(cbMenuItem);
		cbMenuItem.addActionListener
					(new ColorListener(Color.blue));
		submenu.add(cbMenuItem);

		cbMenuItem = 
new JCheckBoxMenuItem("Vert", …) ;
		…

		menu.add(submenu);	// fin du second menu
        
		//Construire le dernier menu Aide a droite
		menu = new JMenu("Aide");
		menu.setMnemonic(KeyEvent.VK_A);        			
		menuBar.add(Box.createHorizontalGlue());
		menuBar.add(menu);
    
	}

	// les classes internes ecouteurs
	// d’items des menus

	class TypeListener implements ActionListener {
		private int type;
        
		TypeListener(int type) {
			this.type = type;
		}
        
		public void actionPerformed(ActionEvent e) {
			elementType = type;   
		}
	}

	class ColorListener implements ActionListener {
		private Color color;
        
		ColorListener(Color color) {
			this.color = color;
		}
        
		public void actionPerformed(ActionEvent e) {
			elementColor = color;
		}
	}
    
	// les accesseurs de elementColor et elementType
	public Color getElementColor() {
		return elementColor;
	}
	public int getElementType() {
		return elementType;
	}
}