Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème avec action sur JMenuItem

    20 mai 2011 à 18:47:18

    Bonjour,

    Voila mon problème :

    Je dois réaliser un projet (Démineur) en java avec pour obligation d'utiliser la class Grille (Grille.java) et et la class Clic (Clic.java)

    mon but est de lancer mon démineur a l'aide d'un menu. mais quand je le lance il plante (impossible de quitter le programme sans fermer le terminale).
    Si je lance mon démineur sans le menu il n'y a aucun problème.

    J'ai juste mis la partie qui pose problème (voir commentaire fichier Test.java) :

    Test.java
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    
    public class Test extends JFrame implements ActionListener
    {
        /**
        *les composants de la fenêtre
        */
        JMenuBar barreDeMenu;//la barre de menu
        //le sous-menu habituel
        JMenu fichier;
        JMenuItem jouer;
    
        public Test()
        {
            super("Test : Demineur");
    
            //création du menu
            jouer = new JMenuItem("Lancer");
            jouer.addActionListener(this);//ajout de l'écouteur
            fichier = new JMenu("Fichier");
            fichier.add(jouer);
    
            barreDeMenu = new JMenuBar();
            barreDeMenu.add(fichier);
    
            //on ajoute enfin la barre de menu à la fenêtre
            setJMenuBar(barreDeMenu);
    
    
            //les propriétés de la fenêtre
            setSize(400, 200);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);
        }
    
        //on redéfini la méthode de l'ActionListener
        public void actionPerformed(ActionEvent e)
        {
            //on regarde si l'écouteur capte le bouton quitter
            if(e.getSource()==jouer)
            {
                Grille g = new Grille(10,10);
    			Clic c = g.clicCase();
    			// c'est "Clic c = g.clicCase();" qui pose problème.
            }
        }
    
        /**
        *le programme permettant de créer la fenêtre
        */
        public static void main(String[] args)
        {
            new Test();
        }
    }
    



    Grille.java
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.lang.IllegalArgumentException;
    
    /** Cette classe permet de créer et de gérer une interface graphique présentant une grille. <BR><BR>
     *  Exemple d'utilisation : <BR>
     *		<I>Grille g = new Grille(30,10);<BR>
     *  		Clic c = g.clicCase();<BR>
     *		g.modifCase(c.x,c.y,'X',Color.RED,Color.LIGHT_GRAY);
     * 		g.afficheMessage("BOUM, vous êtes mort!");<BR><BR></I>
     *  @author Frédéric Fürst*/
    public class Grille extends JFrame implements MouseListener{
    	
    	private JButton[][] cases;
    	private int border = 20;
    	private int caseDim = 20;
    	private MouseEvent clic;
    	
    	/** Crée une interface graphique permettant d'afficher une grille avec largeur*longueur cases. La grille doit contenir au moins une case. Les cases de la grille contiennent chacune un caractère qui est *  initialement un blanc ' '. Les couleurs initiales sont Color.WHITE pour le fond des cases et Color.BLACK pour les caractères. */
    	public Grille(int largeur, int hauteur) throws IllegalArgumentException{
    		super("DEMINEUR");
    		if(largeur<1 || hauteur<1) throw new IllegalArgumentException("La grille doit contenir au moins une case!");
    		this.setLayout(new GridLayout(hauteur,largeur));
    		this.cases = new JButton[largeur][hauteur];
    		JButton jb;
    		for(int i = 0;i<hauteur;i++){
    			for(int j = 0;j<largeur;j++){
    				jb = new JButton(" ");
    				jb.setPreferredSize(new Dimension(caseDim,caseDim));
    				jb.addMouseListener(this);
    				jb.setFont(jb.getFont().deriveFont((float) (caseDim*3/4)));
    				jb.setBackground(Color.WHITE);
    				jb.setForeground(Color.BLACK);
    				jb.setMargin(new Insets(0,0,0,0));
    				this.getContentPane().add(jb);
    				this.cases[j][i] = jb;
    			}
    		}
    		this.pack();
    		this.setResizable(false);
    		this.setLocation((java.awt.Toolkit.getDefaultToolkit().getScreenSize().width-this.getWidth())/2,(java.awt.Toolkit.getDefaultToolkit().getScreenSize().height-this.getHeight())/2);
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		this.setVisible(true);
    	}
    	
    	/** @deprecated */
    	public void mouseClicked(MouseEvent e){
    		this.setClic(e);
    		synchronized(this){
    			this.notify();
    		}
    	}
    	
    	/** @deprecated */
    	public void mouseEntered(MouseEvent e){}
    	
    	/** @deprecated */
    	public void mouseExited(MouseEvent e){}
    	
    	/** @deprecated */
    	public void mousePressed(MouseEvent e){}
    	
    	/** @deprecated */
    	public void mouseReleased(MouseEvent e){}
    	
    	/** @deprecated */
    	public void setClic(MouseEvent e){
    		this.clic = e;
    	}
    
    	private Point getCoordonnees(JButton jb){
    		for(int i = 0;i<this.cases.length;i++){
    			for(int j = 0;j<this.cases[0].length;j++){
    				if(this.cases[i][j] == jb) return new Point(i,j);
    			}
    		}
    		return null;
    	}
    	
    	/** Retourne un Clic lorsque l'utilisateur clique sur une case. Un Clic est un enregistrement qui possède 3 champs entiers : <BR>
    	 *  x : coordonnée horizontale de la case cliquée<BR>
    	 *  y : coordonnée verticale de la case cliquée<BR>
    	 *  bouton : le numéro du bouton utilisé (0: bouton gauche, 1: bouton du milieu, 2: bouton droit). */
    	public synchronized Clic clicCase(){
    		try{
    			this.wait();
    		}
    		catch(InterruptedException e){}
    		JButton jb = (JButton) this.clic.getSource();
    		jb.transferFocusUpCycle();
    		Point p = this.getCoordonnees((JButton) this.clic.getSource());
    		return new Clic(p.x,p.y,this.clic.getButton()-1);
    	}
    	
    	/** Affiche le message m dans une boite de dialogue. */
    	public void afficheMessage(String m){
    		JOptionPane.showMessageDialog(this,m);
    	}
    
    	/** Modifie le caractère affiché dans la case de coordonnées (x,y), si x et y sont des coordonnées valides. */
    	public void modifCase(int x, int y, char affichage, Color texte, Color fond){
    		if(x>-1 && x<this.cases.length && y>-1 && y<this.cases[0].length){
    			this.cases[x][y].setText(String.valueOf(affichage));
    			this.cases[x][y].setForeground(texte);
    			this.cases[x][y].setBackground(fond);
    			this.repaint();
    		}
    	}	
    	public void modifCase(int x, int y, String affichage, Color texte, Color fond){
    		if(x>-1 && x<this.cases.length && y>-1 && y<this.cases[0].length){
    			this.cases[x][y].setText(String.valueOf(affichage));
    			this.cases[x][y].setForeground(texte);
    			this.cases[x][y].setBackground(fond);
    			this.repaint();
    		}
    	}
    }
    


    Clic.java
    /** Cette classe représente un clic souris sur une case de la grille. <BR><BR>
     *  Exemple d'utilisation : <BR>
     *		<I>Grille g = new Grille(30,10);<BR>
     *  		Clic c = g.clicCase();<BR>
     *		if(c.bouton == 2) g.afficheMessage("Vous avez cliqué sur la case ("+c.x+","+c.y+") avec le bouton droit.");<BR><BR></I>
     *  @author Frédéric Fürst*/
     public class Clic{
    	
    	public int x; // abscisse de la case cliquée
    	public int y; // ordonnée de la case cliquée
    	public int bouton; // 0: bouton gauche, 1: molette du milieu, 2: bouton droit
    	
    	public Clic(int x, int y, int bouton){
    		this.x = x;
    		this.y = y;
    		this.bouton = bouton;
    	}
    	
    }
    


    je vous remercie par avance.
    • Partager sur Facebook
    • Partager sur Twitter
      22 mai 2011 à 21:21:30

      Personne pour m'aider ?
      • Partager sur Facebook
      • Partager sur Twitter
        23 mai 2011 à 11:51:42

        Salut.

        Alors le problème viens du fait que gères mal ton clic. Ce que tu essayes de faire c'est d'attendre un clic alors qu'il faut juste que tu soit prévenu quand il y a un clic sur une case.

        Pour cela tu peux par exemple faire ceci :
        1) Ta classe clic implements ActionListener.
        2) Tu définis donc la méthode Action performed en faisant 1- récupération de l'objet source, 2 - cast en case JButton, 3 - Action souhaité
        3) tu supprime ta méthode clicCase
        4) Dans ton constructeur de Grille tu instancie ta classe Clic.
        5) sur tes boutons tu ajoutes l'instance que tu viens de créer comme écouteur.

        Et ça devrait rouler :)
        • Partager sur Facebook
        • Partager sur Twitter
          23 mai 2011 à 20:33:06

          Merci, mais je dois utiliser et je ne dois pas modifier Grille.java et Clic.java de plus je suis débutant en java donc...

          Mais merci quand même
          • Partager sur Facebook
          • Partager sur Twitter
            24 mai 2011 à 8:52:30

            ??? elles sont codés comme maintenant et tu ne dois pas y toucher du tout ?
            • Partager sur Facebook
            • Partager sur Twitter
              24 mai 2011 à 14:01:48

              Alors le problème viens du fait que les event sont gérés par l'EDT (Event Dispatch Thread). Donc c'est lui qui va gérer la répartition des evenements et effectuer les actions associés. Dans le cas actuel, tout va bien jusqu'à ce que tu lances clicCase() dans ton actionPerformed.
              Pourquoi ça plante ici?
              Parce que c'est l'EDT qui effectue le traitement et que ton thread courant (qui exécute clicCase() se met en attente d'un clic sur un bouton. Le soucis c'est qu'il ne peut plus rien écouter vu qu'il est "en pause". Et donc il ne détecte plus rien.
              si tu lances cette méthode dans thread "normal" alors l'EDT écoute et ton autre thread est en pause.

              Réunion je reviens après si tu n'as pas compris...
              • Partager sur Facebook
              • Partager sur Twitter
                26 mai 2011 à 0:18:05

                en effet, je n’ai pas compris (je débute en java)
                • Partager sur Facebook
                • Partager sur Twitter
                  26 mai 2011 à 15:25:56

                  :/
                  Tu sais ce qu'est thread? Tu sais comment "fonctionne" une interface graphique?
                  Est-ce que tu sais ce que le code qu'on t'a filé est censé faire?
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Problème avec action sur JMenuItem

                  × 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