IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Instancier une classe sans appeler son constructeur ?


Sujet :

avec Java

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2011
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2011
    Messages : 90
    Points : 57
    Points
    57
    Par défaut Instancier une classe sans appeler son constructeur ?
    Bonjour à tous,

    Je suis actuellement en train de développer une calculette avec Swing.

    J'ai découpé mon projet en 2 fichiers .java

    My_Window.java
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    import javax.swing.AbstractButton;
    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JButton;
    import javax.swing.JPanel;
    import javax.swing.JLabel;
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Dimension;
     
    public class My_Window extends JFrame {
     
        private static final String Listeners = null;
        JLabel screen = new JLabel();
        JPanel container = new JPanel();
        JPanel operateurs = new JPanel();
        JPanel numbers = new JPanel();
        JPanel panScreen = new JPanel();
     
        public My_Window()
        {
            this.setTitle("Simple Count");
            this.setSize(300, 400);
            this.setLocationRelativeTo(null);
            this.setResizable(false);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.container.setBackground(Color.GRAY);
            this.setContentPane(container);
            this.setVisible(true);
        }
     
        public void Panel_Police()
        {
            Font police = new Font("Arial", Font.BOLD, 30);
     
            this.screen.setFont(police);
            this.screen.setHorizontalAlignment(JLabel.CENTER);
            this.screen.setPreferredSize(new Dimension(200, 300));
            this.screen.setHorizontalAlignment(JLabel.RIGHT);
            this.screen.setPreferredSize(new Dimension(220, 20));
     
            this.operateurs.setPreferredSize(new Dimension(55, 225));
            this.numbers.setPreferredSize(new Dimension(220, 300));
            this.panScreen.setPreferredSize(new Dimension(220, 50));
        }
     
        public void My_Buttons()
        {
            String[] numbers = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
            String[] pad = {"C", "=", ".", "+", "-", "*", "/"};
            JButton[] nbButtons = new JButton[numbers.length];
            JButton[] opButtons = new JButton[pad.length];
     
            int i = 0;
            while (numbers.length != i)
            {
                nbButtons[i] = new JButton(numbers[i]);
                this.numbers.add(nbButtons[i]);
                nbButtons[i].addActionListener(new Listeners.nbListener()/*new nbListener()*/);
                this.setPreferredSize(new Dimension(50, 100));
                i++;
            }
            i = 0;
            while (pad.length != i)
            {
                if (pad[i] != "C")
                    this.operateurs.add(new JButton(pad[i]));
                else
                    this.operateurs.add(new JButton(pad[i])).setForeground(Color.red);
                this.setPreferredSize(new Dimension(200, 100));
                i++;
            }
     
        }
     
        public void Add_to_container()
        {
            this.panScreen.add(screen);
            this.panScreen.setBorder(BorderFactory.createLineBorder(Color.black));
            this.container.add(panScreen, BorderLayout.NORTH);
            this.container.add(numbers, BorderLayout.CENTER);
            this.container.add(operateurs, BorderLayout.EAST);        
        }
     
        public JLabel getScreen()
        {
            return (this.screen);
        }
    }
    Listeners.java (fichier où se trouvera les listeners de chaque opérateur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import java.awt.event.ActionListener;
     
    import javax.swing.JButton;
    import javax.swing.JLabel;
     
    import java.awt.event.ActionEvent;
     
    public class Listeners {
     
        static My_Window display = new My_Window();     // Problème ici : Appel du constructeur qui lance une autre fenêtre
        static JLabel screen = display.getScreen();
     
        public static class nbListener implements ActionListener {
     
            public void actionPerformed(ActionEvent e) {
                String text = ((JButton) e.getSource()).getText();
                screen.setText(text);                // Problème ici : ça ne fonctionne pas...
                }
     
            }
    }
    Deux problèmes dans tout ça :

    - Lorsque j'appuie sur une touche "nbListener", le constructeur de My_Window est appelé et me lance donc une deuxième fenêtre.
    Je sais que je peux retirer tout le code se trouvant dans le constructeur pour le mettre dans une autre fonction mais cette façon ne me plait pas et j'aimerais connaître une solution alternative "propre".

    - "screen.setText(text);" ne fonctionne pas, je suppose que la variable screen est loupée. Si je mets la classe nbListener dans le fichier My_Window, ça fonctionne parfaitement.

    J'ai fait beaucoup de recherches, y compris sur ce forum, et je n'ai pas su trouver une solution à mon problème.

    Quelqu'un saurait-il m'indiquer comment résoudre ces problème ?

    Merci d'avance pour votre aide.

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    On ne peut pas créer une instance de classe sans exécuter au moins un constructeur : il est là justement pour initialiser l'instance à sa création. De toute manière, même sans instancier la classe Listener, vu que la variable est static, tu aurais une seconde fenêtre dès que tu accèderais par exemple à une constante de la classe : le code statit s'éxécute avant le constructeur, au premier chargement de la classe dès qu'elle est référencée. A fortiori si on l'instancie.

    Quand tu as besoin d'une référence d'une instance dans une autre classe, justement, passe-là en paramètre du constructeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static class nbListener implements ActionListener {
     
           private  My_Window display;
     
           public nbListener( My_Window display) {
                this.display=display;
           }
     
    		public void actionPerformed(ActionEvent e) {
    			String text = ((JButton) e.getSource()).getText();
    			display.getScreen().setText(text);              
    			}
     
    		}
    Et pour l'instanciation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nbButtons[i].addActionListener(new Listeners.nbListener( this )); // this étant la référence de My_Window elle-même
    A noter, que comme ton listener n'a de raison d'exister que dans ta fenêtre, autant mettre cette classe dans My_Window. Si elle n'est pas statique, tu n'auras même pas besoin de passer la référence de la fenêtre : elle y aura accès directement, et même aura accès directement à la variable scrren, et tu pourras écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private class NbListener implements ActionListener { // note que la convetion Java pour les noms de classes est qu'il commence par une majuscule
     
     
        public void actionPerformed(ActionEvent e) {
            String text = ((JButton) e.getSource()).getText();
    	screen.setText(text);              
        }
     
    }
    On peut aussi faire comme tu as fait (ou une classe à part), en la rendant indépendante de My_Window :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static class NbListener implements ActionListener {
     
           private JLabel label;
     
           public nbListener( JLabel label ) {
                this.label=label;
           }
     
           public void actionPerformed(ActionEvent e) {
    	     String text = ((JButton) e.getSource()).getText();
    	     label.setText(text);              
           }
     
    }
    Et pour l'instanciation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nbButtons[i].addActionListener(new Listeners.nbListener( screen ));
    Tu pourrais même rendre le listener indépendant de la notion de JButton, en utilisant la commande de l'action pour indiquer le texte que tu vas chercher actuellement dans le texte du JButton.

    A noter qu'en Java 8, les lambda-expressions permettent de faire ça de manière encore plus simple, sans créer de classe particulière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nbButtons[i].addActionListener( (e) -> screen.setText( nbButtons[i].getText() ) );
    tout simplement.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2011
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2011
    Messages : 90
    Points : 57
    Points
    57
    Par défaut
    Je suis époustoufler par votre réponse.
    Un grand merci.

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 807
    Points
    48 807
    Par défaut
    Citation Envoyé par joel.drigo Voir le message
    Salut,

    On ne peut pas créer une instance de classe sans exécuter au moins un constructeur
    Pour l'anecdote, on peut, mais il ne faut pas! Le cas typique d'instanciation sans passer par le constructeur: la désérialisation

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2011
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2011
    Messages : 90
    Points : 57
    Points
    57
    Par défaut
    Merci encore joel.drigo, vos explications sont parfaites et vous m'avez complètement débloqué.

    Un grand merci.

Discussions similaires

  1. Instancier une classe sans connaitre son nom
    Par Molkobain dans le forum Langage
    Réponses: 8
    Dernier message: 16/02/2009, 14h49
  2. Reflection : Créer une instance sans appeler le constructeur
    Par cboun94 dans le forum Framework .NET
    Réponses: 8
    Dernier message: 17/12/2007, 17h26
  3. instancier une variable sans appeller de methode?
    Par debutant_linux dans le forum Ruby on Rails
    Réponses: 4
    Dernier message: 05/07/2007, 11h31
  4. Réponses: 6
    Dernier message: 06/04/2007, 21h20
  5. Réponses: 7
    Dernier message: 29/11/2006, 11h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo