Partage
  • Partager sur Facebook
  • Partager sur Twitter

pattern mvc

Sujet résolu
    6 avril 2010 à 12:27:14

    Bonjour,

    J'essaye d'utiliser le pattern mvc (pour la 1iere fois) mais j'ai quelques soucis...
    Je voudrais savoir ce qui ne va pas dans mon architecture.
    Je vous mets les classes importantes dites moi si il manque des choses
    Tous mes objets (Ball, Queue, Table,...) héritent de Shape
    Tous mes dessins(BallView,QueueView,...) héritent de ShapeView

    VUE:
    Classe GameView:

    package view;
    
    import java.awt.Color;
    
    
    public class GameView extends JPanel {
    
    	private static final long serialVersionUID = 1L;
    	private Dimension dimWindow;
    	private Drawing drawingStatic;
    	private Drawing drawingDynamic;
    	ArrayList<Ball> ballsList = new ArrayList<Ball>();
    	ArrayList<Hole> holesList = new ArrayList<Hole>();
    
    	
    	/**
    	 * Par défaut
    	 */
    	public GameView(Dimension dimWindow){
    		super();
    		this.setSize(dimWindow);
    		this.setBounds(0, 0, dimWindow.width, dimWindow.height);
    		this.dimWindow = dimWindow;
    		drawingStatic = new Drawing(this);
    		drawingStatic.setBounds(this.getBounds());
    		drawingDynamic = new Drawing(drawingStatic);
    		initialiseComponents();	
    
    // PROBLEME LORSQUE JE DECOMMENTE CES LIGNES J AI UNE BOUCLE INFINIE--->notifier fonctionne pas???
    
    //		while(true)
    //		{
    //			System.out.println("yo");
    //			ballsList.get(15).move();           
    //			ballsList.get(15).notifyObserver();
    //			try{
    //				Thread.sleep(25);
    //			}
    //			catch(InterruptedException e) {}
    //		}
    	}
    	
    	private void initialiseComponents()
    	{
    		
    		int radius = 12;
    		
    		//boule rouge
    		for (int curBall = 0; curBall < 15; curBall++)
    		{
    			Ball ball;
    			int diameter = 2*radius;
    			if(curBall < 5)
    				ball = new Ball(new Point(dimWindow.width/2 - 2*diameter + curBall*diameter,50 ), Color.red, radius);
    			else if(curBall < 9)
    				ball = new Ball(new Point(dimWindow.width/2 - 3*diameter/2 + (curBall-5)*diameter ,50 + diameter), Color.red, radius);
    			else if(curBall < 12)
    				ball = new Ball(new Point(dimWindow.width/2 - diameter + (curBall-9)*diameter ,50 + 2*diameter), Color.red, radius);
    			else if(curBall < 14)
    				ball = new Ball(new Point(dimWindow.width/2 - diameter/2 + (curBall-12)*diameter ,50 + 3*diameter), Color.red, radius);
    			else
    				ball = new Ball(new Point(dimWindow.width/2 , 50 + 4*diameter), Color.red, radius);
    			
    			BallView ballView = new BallView(ball.getPosition(),ball.getColor(),ball.getRadius(), drawingDynamic);
    			ball.addObserver(ballView);
    			ballsList.add(ball);		
    			drawingDynamic.addShape(ballView);
    			
    		}
    		
    		//boule blanche
    		Ball ball = new Ball(new Point(dimWindow.width/2-radius/2, dimWindow.height -100), Color.white,radius);
    		BallView ballView = new BallView(ball.getPosition(),ball.getColor(),ball.getRadius(), drawingDynamic);
    		ball.addObserver(ballView);
    		drawingDynamic.addShape(ballView);
    		ballsList.add(ball);
    		
    		Point pos = ball.getPosition();
    		
    		//queue
    		Queue queue = new Queue(pos);
    		QueueView queueView = new QueueView(drawingDynamic);
    		QueueMouseListener queueControler = new QueueMouseListener(queue);
    		queue.addObserver(queueView);
    		drawingDynamic.addShape(queueView);
    		
    		
    		queue.notifyObserver();
    		
    		//table
    		Dimension dimTable = new Dimension(500, 600);
    		Table table = new Table(dimTable, ballsList, holesList, new Point(30,30));
    		TableView tableView = new TableView(table.getDimension(),table.getPosition(), drawingStatic);
    		table.addObserver(tableView);
    		drawingStatic.addShape(tableView);
    		
    		//trous
    		for(int i = 0; i < 6; i++)
    		{
    			int cur = i%2;
    			Hole hole = null;
    			int radiusHoles = 20;
    			if(i < 2)
    				hole = new Hole(new Point(cur*(dimWindow.width-2*25)+25,25), radiusHoles);
    			else if(i < 4)
    				hole = new Hole(new Point(cur*(dimWindow.width-2*25)+25,dimWindow.height/2 - radiusHoles/2), radiusHoles);
    			else 
    				hole = new Hole(new Point(cur*(dimWindow.width-2*25)+25,dimWindow.height - radiusHoles), radiusHoles);
    			
    			HoleView holeView = new HoleView(hole.getPosition(), hole.getRadius(), drawingStatic);
    			hole.addObserver(holeView);
    			holesList.add(hole);
    			drawingStatic.addShape(holeView);
    		}
    	}
    	
    	public void paintComponent(Graphics g){
    	
    		this.drawingStatic.paintComponent(g);
    		this.drawingDynamic.paintComponent(g);
    	}
    	
    }
    



    Classe Drawing :

    package view;
    
    import java.awt.Graphics;
    
    
    public class Drawing extends JPanel implements Iterable<ShapeView>{
    	
    	private static final long serialVersionUID = 1L;
    	protected JPanel parent; 
    	ArrayList<ShapeView> shapes;
    		
    		public Drawing(JPanel pan){
    			super();
    			this.parent = pan;
    			shapes = new ArrayList<ShapeView>();
    		}
    		// Implementation de l'interface d'iteration
    		public Iterator<ShapeView> iterator(){
    			return shapes.iterator();
    		}
    		
    		public void addShape(ShapeView s){
    			shapes.add(s);
    			this.repaint();
    		}
    		
    		public void paintComponent(Graphics g) {
    			this.parent.getGraphicsConfiguration();
    			for(ShapeView s : shapes){
    				s.paint(g);
    			}
    		}
    		
    		//RÈinitialise le Shape (cfr mise ‡ jour)
    		public void clear(){
    			shapes.clear();
    			this.repaint();
    		}
    		
    		
    	}
    



    Classe ShapeView:

    package view;
    
    import java.awt.Graphics;
    
    public abstract class ShapeView implements Observer{
    
    	private static final long serialVersionUID = 1L;
    	// Origine du dessin par rapport ‡ la table.
    	protected Point position;
    	protected Drawing drawing;
    	
    	public void setPosition(Point p){
    		position = p;
    	}
    	public Point getPosition(){
    		return position;
    	}
    	// Dessine la forme sur un objet graphic.
    	public abstract void paint(Graphics g);
    	
    	@Override
    	public void update(Point p) {
    		position = p;
    		drawing.repaint();
    	}
    }
    



    CONTROLEUR:
    Classe QueueMouseListener:

    package controler;
    
    import java.awt.Point;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    
    import model.Queue;
    
    public class QueueMouseListener implements MouseListener{
    
    	private Point position;
    	private int width;
    	private int height;
    	private Queue queue;
    	
    	public QueueMouseListener(Queue queue){
    		this.position = queue.getPosition();
    		this.width = queue.getWidth();
    		this.height = queue.getHeight();
    		this.queue = queue;
    		queue.addMouseListener(this);
    	}
    	
    	@Override
    	public void mouseClicked(MouseEvent e) {
    		// TODO Auto-generated method stub
    		if(e.getX() > this.position.x && e.getX() < (this.position.x + this.width) && e.getY() > this.position.y && e.getY() < (this.position.y + this.height))
    		{
    			this.position.y = e.getY();
    			queue.notifyObserver();
    		}
    		
    		
    	}
    
    	@Override
    	public void mouseEntered(MouseEvent e) {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void mouseExited(MouseEvent e) {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void mousePressed(MouseEvent e) {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void mouseReleased(MouseEvent e) {
    		// TODO Auto-generated method stub
    		
    	}
    
    }
    



    MODELE:
    Classe Shape:

    package model;
    
    import java.awt.Point;
    import java.util.ArrayList;
    
    import javax.swing.JPanel;
    
    // Classe abstraite de type forme dessinable.
    
    public abstract class Shape extends JPanel implements Observable{
    	
    	private static final long serialVersionUID = 1L;
    	// Origine du dessin par rapport ‡ la table.
    	protected Point position;
    	private ArrayList<Observer> listObserver = new ArrayList<Observer>();
    	
    	public void setPosition(Point p){
    		position = p;
    	}
    	public Point getPosition(){
    		return position;
    	}
    
    	
    	/*********************************************************************
    	 * 				
    	 * 					IMPLÉMENTATION PATTERN OBSERVER
    	 * 
    	 ********************************************************************** */
    
    	public void addObserver(Observer obs){
    		this.listObserver.add(obs);
    	}
    	
    	@Override
    	public void notifyObserver() {
    		// TODO Auto-generated method stub
    		for(Observer obs : listObserver)
    			obs.update(this.position);
    	}
    
    	@Override
    	public void removeObserver() {
    		// TODO Auto-generated method stub
    		listObserver = new ArrayList<Observer>();
    	}
    }
    




    Interface Observable:

    package model;
    
    public interface Observable {
    
    	public void addObserver(Observer obs);
    	public void removeObserver();
    	public void notifyObserver();
    	
    }
    



    Interface Observer:

    package model;
    
    import java.awt.Point;
    
    
    public interface Observer {
    	public void update(Point p);
    }
    



    Questions:

    • Lorsque je décommente le while(true) dans GameView ça plante....-->soucis avec notifyObserver??
    • Lorsque je place la queue je n'arrive pas à la décaler par rapport à la boule blanche car celle-ci suit le mouvement
    • mon MouseListener ne marche pas


    Voilou merci d'avance pour votre aide
    • Partager sur Facebook
    • Partager sur Twitter
      6 avril 2010 à 13:03:22

      Les évènements claviers peuvent seulement être interceptés sur un Component. Il y'a également la possibilité de savoir si un objet affiché à l'écran a été cliquée, pour cela il doit implémenter java.awt.Shape et redéfinir la méthode hit() de Graphics2D... Méthode pas très flexible à mon avis.

      Gaffe à tes noms de méthodes : déjà Shape, elle existe déjà alors attention aux imports.
      La méthode paint() existe déjà aussi, j'ai peur que ça crée un conflit très rapidement si tu ne fais pas attention.
      On met toujours super.paintComponent(g) dans la redéfinition de paintComponent().
      On n'appelle jamais paintComponent() directement, on utilise repaint() et on laisse Swing faire le boulot. Ou alors on se tourne vers une méthode d'active rendering.

      Je pense que le problème de la boucle infinie est lié avec le thread de Swing complètement surchargé et donc il ne reçoit plus les évènements. Place ta boucle infinie dans un autre thread, et utilise le code suivant pour invoquer ton notify() dans le thread de Swing :
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            ballsList.get(15).notifyObserver();
         }
      });
      


      J'espèrerais que cela suffise...

      Bon courage :)
      • Partager sur Facebook
      • Partager sur Twitter
        6 avril 2010 à 14:27:06

        Merci pour ta réponse elmh
        je ne sais pas très bien utiliser les threads donc je ne vois pas trop où mettre le code que tu me donnes.

        Sinon pour les autres questions tu n'aurais pas une idée?
        Le passage par le notifyObserver a l'air cohérent?

        Voila la dernière version du QueueMouseListener:

        package controler;
        
        import java.awt.event.MouseEvent;
        import java.awt.event.MouseListener;
        import java.awt.event.MouseMotionListener;
        
        import model.Queue;
        import model.Shape;
        
        public class QueueMouseListener implements MouseListener, MouseMotionListener{
        
        	private Shape currentShape = null;
        	private Queue queue;
        	
        	public QueueMouseListener(Queue queue){
        		this.queue = queue;
        		queue.addMouseListener(this);
        		queue.addMouseMotionListener(this);
        		System.out.println(queue.getPosition());
        	}
        	
        	@Override
        	public void mouseClicked(MouseEvent e) {
        		// TODO Auto-generated method stub
        		if(queue.isOn(e.getPoint()))
        			currentShape = queue;
        		System.out.println(currentShape);
        		
        		
        	}
        
        	@Override
        	public void mouseEntered(MouseEvent e) {
        		// TODO Auto-generated method stub
        		if(queue.isOn(e.getPoint()))
        			currentShape = queue;
        		System.out.println(currentShape);
        	}
        
        	@Override
        	public void mouseExited(MouseEvent e) {
        		// TODO Auto-generated method stub
        		
        	}
        
        	@Override
        	public void mousePressed(MouseEvent e) {
        		// TODO Auto-generated method stub
        		if(queue.isOn(e.getPoint()))
        			currentShape = queue;
        		System.out.println(currentShape);
        	}
        
        	@Override
        	public void mouseReleased(MouseEvent e) {
        		// TODO Auto-generated method stub
        		
        	}
        
        	@Override
        	public void mouseDragged(MouseEvent e) {
        		// TODO Auto-generated method stub
        		System.out.println(currentShape);
        		if(currentShape != null)
        		{
        			currentShape.getPosition().y = e.getY();
        			System.out.println(currentShape.getPosition().y);
        			currentShape.notifyObserver();
        		}
        	}
        
        	@Override
        	public void mouseMoved(MouseEvent e) {
        		// TODO Auto-generated method stub
        		
        	}
        
        }
        


        Malheureusement rien ne se passe lorsque je clique sur la queue... :(
        • Partager sur Facebook
        • Partager sur Twitter
          6 avril 2010 à 15:26:02

          Je ne cherche pas à savoir comment fonctionne ton code, surtout avec le modèle MVC, c'est bien trop chiant à déchiffrer.
          J'ai juste donné une floppée de remarques pour rendre ton code meilleur.

          Je vais me répéter car je pense que c'était pas clair : Tu peux créer autant de MouseListener que tu veux, pas de soucis, seulement, tu pourras ne les ajouter QUE sur des Component (ce terme regroupe tout ce qui en hérite... JPanel par exemple).
          Par exemple dans QueueMouseListener je vois ceci : queue.addMouseListener(this);
          Seulement, Queue hérite-t-elle (directement ou non) d'un Component ? Autrement dit, est-ce qu'au moins une de ses classes mère hérite de Component ?

          Pour ta deuxième question je n'en ai aucune idée, c'est toi le programmeur qui connaît ton code. Ca me semble plutôt être un problème de maths qu'autre chose, une mauvaise mise à jour de coordonnées par exemple.

          Enfin, si tu ne sais pas utiliser les Thread, tu vas devoir apprendre, car pour faire un jeu correct c'est indispensable.
          Il te faudrait créer une nouvelle tâche (un Runnable) qui contiendrait ta boucle infinie. Cette dernière doit absolument s'effectuer dans un autre Thread que celui de Swing.
          • Partager sur Facebook
          • Partager sur Twitter
            6 avril 2010 à 16:31:45

            Ok merci pour ces précisions.

            Alors oui queue hérite d'un component par Shape qui hérite lui-même de JPanel, c'est pour cela que je ne comprends pas très bien pourquoi ça ne marche pas...

            Sinon pour les threads je savais que j'allais devoir m'y frotter à un moment mais comme j'essaye d'abord de m'occuper de l'affichage pur avant le mouvement je n'ai pas encore approfondit.

            Pour ce qui est de la position de la queue par rapport à la balle je vais encore y réfléchir mais c'est assez déroutant... :p

            J'ai encore un petite question par rapport à l'affichage de ma table. Apparemment, lorsqu'on positionne un JPanel dans une JFrame celui-ci tient compte de la barre de titre de la JFrame et donc il y a un décalage. Je te mets une image pour que tu vois le problème.

            http://www.siteduzero.com/upload-216.h [...] extarea=texte

            On me dit de faire avec des layouts c'est bien ce que j'ai fait mais avec ou sans BorderLayout.CENTER ça marche pas :euh:
            • Partager sur Facebook
            • Partager sur Twitter
              6 avril 2010 à 20:54:00

              Ton lien ne marche pas il est lié à tes privilèges de compte donc je ne suis pas autorisé à regarder.

              Je suis pas du tout un expert dans l'esthétisme, donc pas d'aide sur ce coup là.
              J'imagine que t'as voulu centrer un Component ; et effectivement la JMenuBar est prise en compte.
              Je sais déjà que y'a des méthodes pour bien centrer, au moins tu sais que tu chercheras pas dans le vide ^^

              Quant au BorderLayout, il ne centre rien du tout, sa variable static CENTER sert juste à indiquer "vers le milieu". Sauf que quand y'a qu'un Component, ben il prend toute la place.
              Faut peut-être jouer avec les preferredSize remarque.
              • Partager sur Facebook
              • Partager sur Twitter
                6 avril 2010 à 21:29:26

                mmm ok je ne sais pas comment ajouter une image alors :p
                sinon oui il doit exister des méthodes pour centrer mais justement je ne les trouve pas dans l'api java... :( que faire?? j'ai aussi tenté les setPreferredSize aussi sans succès (mais peut-être mal...)

                Bref de toute façon je te remercie pour ton aide
                • Partager sur Facebook
                • Partager sur Twitter
                  8 avril 2010 à 12:13:20

                  Hello,

                  J'ai finalement trouvé le problème. En fait, je positionnais mal mes dessins dans mon objet graphics.
                  Et pour la boule blanche et la queue, je n'avais pas fait de new Point() pour la position donc je gardais celle de la boule blanche.
                  Voila merci beaucoup elmh

                  • Partager sur Facebook
                  • Partager sur Twitter

                  pattern mvc

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown