Problème avec les Listeners en java

HommeCocoa

Membre actif
3 Janvier 2003
173
0
Vevey - Suisse
Bonjour,

J'ai une classe Application qui hérite de la classe JFrame et implement la classe ActionListener. Donc au sein de cette classe, je peux très facilement travailler avec mes divers objet graphique tel que des JTables.

Cependant (et c'est là qu'apparaît le problème) j'ai une autre classe (mettons AutreFrame) qui elle hérite aussi de JFrame qui sert de panel dans lequel on vient entrer des informations qui seront ensuite affichée dans le JTable de la classe Application.

C'est depuis cette classe Application que "j'invoque" mon instance de AutreFrame et je lui attribue Application comme ActionListener.

Mais le soucis c'est que je n'arrive pas à récuperer les valeurs des champs de texte depuis la classe Application.

Voici ce que j'ai essayé de faire

String nom = autreFrame.champsText.getText();

où: autreFrame est une instance de AutreFrame et champsText une instance de JTextField construit dans AutreFrame. Et comme cité plus haut le bouton qui sert à lancer l'action est dans AutreFrame mais est écouté par Application

Et biensur AutreFrame est une classe public.

Je comprend pas comment faire alors pour récuperer ces valeurs.... :confused:


Hou lalala je viens de relire, c'est très peu clair :heu: mais j'ai aussi des difficultés à être clair on dirait...

Merci à ceux qui auront le courage de lire...
David
 
Salut,

Tout d'abord, peux-tu préciser si:
  • la frame application ne reçoit jamais le message envoyé par le bouton ?
  • le getText() ne renvoie pas la valeur que tu attends ?



Sinon, d'une manière générale, il peut être plus propre d'utiliser un modèle pour la collecte de tes données. Le principe de fonctionnement est très simple:
  • un modèle POJO qui représente tes données (une simple classe objet avec plein d'attributs et des getter/setter)
  • ce modèle est Observable
  • toutes tes frames (ou panels) qui affichent des infos du modèle sont Observer et écoutent les modifications du modèle

Ainsi, dans le code de ton bouton (actionlistener), tu ne fais que des modifs du modèle et tu déclenches la mise à jour... et tous les autres controles seront à jour.

Le risque est que ton code risque de devenir très rapidement:
  • illisible
  • non maintenable (et peu stable)
  • pas (ou peu) évolutif


P.S. aux puristes: c'est une vision très très simplifiée (et simpliste) des patterns document/vue et des architectures MVC.... histoire de ne pas effrayé notre amis
 
  • J’aime
Réactions: molgow
:rose: Aie Aie Aie pour vous donner un exemple j'ai récrit une "application" similaire mais un peu simplifiée et maintenant tout fonctionne correctement... Je m'arrache les cheveux là...

Par contre il y a encore un truc qui ne me satisfait pas.

Regardez mes fichiers:

Le Main:

Bloc de code:
public class Main
{


	public static void main(String[] args)
	{
		Application application = new Application();

	}

}

Classe Application

Bloc de code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class Application extends JFrame implements ActionListener
{
	public JButton boutonApplication;
	public AutreFrame autreFrame;

	public Application()
	{
		this.setTitle("Application");
		this.setBounds(200,200,640,480);
		
		boutonApplication = new JButton("AutreFrame");
		
		boutonApplication.addActionListener(this);
		this.add(boutonApplication);
		
		this.setVisible(true);
	}
	
	
	
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource()==boutonApplication)
		{
			autreFrame = new AutreFrame();
			
			autreFrame.boutonAutreFrame.addActionListener(this);  //<== ligne qui fonctionne mais qui me déplait
		}
		
		if(e.getSource()==autreFrame.boutonAutreFrame)
		{
			System.out.println(autreFrame.textFieldAutreFrame.getText());
		}
		
	}

}


et la classe AutreFrame

Bloc de code:
import java.awt.GridLayout;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

public class AutreFrame extends JFrame
{
	public JButton boutonAutreFrame;
	public JTextField textFieldAutreFrame;

	public AutreFrame()
	{
		this.setTitle("Autre Frame");
		this.setBounds(100,100,250,50);
		this.setLayout(new GridLayout(1,2));
		
		textFieldAutreFrame = new JTextField();
		boutonAutreFrame = new JButton("Ok");
		
		//boutonAutreFrame.addActionListener(application);  <== ligne commentée qui ne fonctionne pas...
		
		this.add(textFieldAutreFrame);
		this.add(boutonAutreFrame);
		
		this.setVisible(true);
	}
	
}

Ce qui me déplait c'est que je suis obligé d'accrocher l'ActionListener au boutonAutreFrame depuis la classe Application au moment ou je crée l'instance autreFrame alors que j'aimerais le faire depuis la Classe AutreFrame comme j'ai tenté à la ligne commentée (15ème ligne) dans son constructeur.
 
Voici du code afin d'illustrer mes propos.

il est prêt à compiler. On y voit 2 frames qui discutent entre-elles autour d'un modèle commun.

Un controller gère les actions déclenchées.



Bloc de code:
/*
 * Created on 5 juin 2006
 */
package org.gibus.macge;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * Les classes ont toutes ?t? plac?es dans le m?me fichier pour plus de commodit? ? l'upload sur le forum.
 * 
 * @author GrandGibus
 * copyrights MacG?n?ration
 */
public class DemoDocumentVue {

    /**
     * Le mod?le... l'?pine dorsale de ton projet. C'est lui qui repr?sente les donn?es de ton programme.
     * Celui-ci ne pr?sente aucune fonction m?tier... c'est un POJO.
     * A noter qu'on peut ?galement utilser les fonctions des Beans et leurs propriet?s au lieu de Observable ;-)
     * @author GrandGibus
     *
     */
    private static class MonModele extends Observable {
        private String nom;
        private int age;
        public MonModele(String nom, int age) {
            this.nom = nom;
            this.age = age;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
            setChanged();
        }
        public String getNom() {
            return nom;
        }
        public void setNom(String nom) {
            this.nom = nom;
            setChanged();
        }
    }
    
    /**
     * La classe se met automatiquement ? jour sur les notifications du mod?le qu'elle ?coute.<br />
     * Ce n'est pas elle qui a la responsabilit? d'?diter le mod?le: c'est le travail du controlleur
     * @author GrandGibus
     */
    private static class MonPanel1 extends JPanel implements Observer {
        private JTextField tfNom;
        private JTextField tfAge;
        private JButton btnUpdate;
        public MonPanel1() {
            initLayout();
        }
        
        private void initLayout() {
            this.setBorder(BorderFactory.createTitledBorder("Mon Panel1"));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(7, 7, 7, 7);
            gbc.anchor = GridBagConstraints.EAST; 
            gbc.fill = GridBagConstraints.NONE;
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 0;
            gbc.weighty = 0;
            this.add(new JLabel("Nom :"), gbc);
            gbc.gridy++;
            this.add(new JLabel("Age :"), gbc);
            
            gbc.gridx = 1;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.WEST;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            tfNom = new JTextField(30);
            this.add(tfNom, gbc);
            gbc.gridy++;
            tfAge = new JTextField(3);
            this.add(tfAge, gbc);
            
            gbc.gridx = 2;
            gbc.gridy = 0;
            gbc.gridwidth = 1;
            gbc.gridheight = 2;
            gbc.weightx = 0;
            gbc.weighty = 1;
            btnUpdate = new JButton("Mise ? jour");
            this.add(btnUpdate, gbc);
        }
        
        public void update(Observable o, Object arg) {
            if (o != null && o instanceof MonModele) {
                MonModele m = (MonModele)o;
                this.tfNom.setText(m.getNom());
                this.tfAge.setText(Integer.toString(m.getAge()));
            }
        }

        public JButton getBtnUpdate() {
            return btnUpdate;
        }
        
        public String getNomEdite() {
            return tfNom.getText();
        }
        public int getAgeEdite() {
            return Integer.parseInt(tfAge.getText());
        }
    }
    
    /**
     * La vue est branch?e sur le mod?le <em>depuis l'ext?rieur</em>.
     * A noter que la vue ne stocke ni le mod?le, ni le controlleur, ni d'autres vues.
     * @author GrandGibus
     */
    private static class MonPanel2 extends JPanel implements Observer {
        private JLabel lblAge;
        private JButton btnEffacer;
        public MonPanel2() {
            initLayout();
        }
        
        private void initLayout() {
            this.setLayout(new BorderLayout());
            this.setBorder(BorderFactory.createTitledBorder("Mon Panel2"));
            lblAge = new JLabel();
            this.add(lblAge, BorderLayout.NORTH);
            btnEffacer= new JButton("Effacer");
            this.add(btnEffacer, BorderLayout.SOUTH);
        }
        
        public void update(Observable o, Object arg) {
            if (o != null && o instanceof MonModele) {
                MonModele m = (MonModele)o;
                StringBuffer sb = new StringBuffer();
                if (m.getAge() > 0) {
                    sb.append("Mr ");
                    sb.append(m.getNom());
                    sb.append(" est ag? de ");
                    sb.append(m.getAge());
                    sb.append(" ans.");
                }
                this.lblAge.setText(sb.toString());
            }
        }
        public JButton getBtnEffacer() {
            return btnEffacer;
        }
    }
    
    
    /**
     * Le controlleur a pour but de relier la vue et le mod?le. C'est lui (et pas la vue) qui prend 
     * l'initiative de modifier le mod?le.
     * 
     * @author GrandGibus
     *
     */
    public static class MonControlleur {
        public static void initController(final MonPanel1 pnl, final MonModele mdl) {
            pnl.getBtnUpdate().addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    mdl.setNom(pnl.getNomEdite());
                    mdl.setAge(pnl.getAgeEdite());
                    mdl.notifyObservers();
                }
            });
        }
        public static void initContorller(final MonPanel2 pnl, final MonModele mdl) {
            pnl.getBtnEffacer().addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    mdl.setAge(0);
                    mdl.setNom("");
                    mdl.notifyObservers();
                }
            });
        }
    }
    

    /**
     * L'ossature du programme: 
     * <ol>
     *   <li>on cr?e le mod?le</li>
     *   <li>on cr?e les 2 vues associ?es</li>
     *   <li>on met le controlleur en place</li>
     * </ol>
     * Les 2 frames sont affich?es.
     * @param args
     */
    public static void main(String[] args) {
        MonModele modele = new MonModele("", 0);
        MonPanel1 pnl1 = new MonPanel1();
        modele.addObserver(pnl1);
        MonControlleur.initController(pnl1, modele);
        
        MonPanel2 pnl2 = new MonPanel2();
        modele.addObserver(pnl2);
        MonControlleur.initContorller(pnl2, modele);
        
        // modele init
        modele.setNom("");
        modele.setAge(0);
        modele.notifyObservers();
        
        JFrame frm = new JFrame("MVC D?mo for macg? 1");
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frm.getContentPane().add(pnl1);
        frm.pack();
        frm.show();
        
        frm = new JFrame("MVC D?mo for macg? 2");
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frm.getContentPane().add(pnl2);
        frm.pack();
        frm.show();
    }
}


P.S. tout est packagé dans un seul fichier pour des raisons pratiques ;)
 
Merci beaucoup pour cet exemple très complet! J'essayais justement de chercher des tutoriels ou des exemples de codes là dessus, je suis servi! Je vais commencer à l'étudier dès que j'ai un moment :)
 
J'espère que tu m'en voudras pas, mais j'ai changé le mot "Ecouteurs" en "Listeners" dans le titre :D
J'ai mis à un moment à comprendre quel était le rapport entre tes écouteurs et Java, et d'abord j'ai même cru à un post à rediriger sur iPodGeneration :D