problem Inner Class

Hello,
I made an inner class for my MouseListener,

private JPanel [] pColonne;
private JPanel panel;
private Puissance4 modèle;

...
//In the Constructor
this.modèle = modèle;
...
panel= new JPanel(new GridLayout (1,7));
for (int i = 0; i < 7; ++i) {
     panel.add(pColonne[i]);
     pColonne[i].add(label);
     pColonne[i].addMouseListener( new MouseListener(){
          public void mouseClicked(MouseEvent e) {
               modèle.jouer(1);
          }
          public void mouseEntered(MouseEvent e) {
               label.setIcon(flèche);
         }
    }
...

I have an error on modèle
says " change modifier of 'modèle' to final "
But why can I acces to 'label' and not to 'modèle' from my inner class ?
Thanks
*sorry of my poor english*
                                                   
LVL 9
matthew016Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

zzynxSoftware engineerCommented:
And what is label?
0
TimYatesCommented:
can you post more of your code?
0
CEHJCommented:
Because your MouseListener is anonymous, you need to declare any variables of its parent you want to access as final
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

CEHJCommented:
You would be better using a named inner class:


pColonne[i].addMouseListener(new PlayerListener());

............


class PlayerListener extends MouseAdapter {
      public void mouseClicked(MouseEvent e) {
            modèle.jouer(1);
      }
      
      public void mouseEntered(MouseEvent e) {
            label.setIcon(flèche);
      }
}
0
zzynxSoftware engineerCommented:
The main question was
>>But why can I acces to 'label' and not to 'modèle' from my inner class ?

So, mine is: how is label defined?
0
TimYatesCommented:
Change:

               modèle.jouer(1);

to

               this.modèle.jouer(1);

I'm guessing you are passing modèle into the method that the for loop is in, and this is being used rather than the actual class instance that you require :-)
0
CEHJCommented:
>>
The main question was
>>But why can I acces to 'label' and not to 'modèle' from my inner class ?
>>

That's unanswerable as the declaration of 'label' is not shown
0
TimYatesCommented:
I reckon it's because there's a situation like this:

  public void whatever( Puissance4 modèle )
  {
     this.modèle = modèle;
      ....
     pColonne[i].addMouseListener( new MouseListener(){
          public void mouseClicked(MouseEvent e) {
               modèle.jouer(1);
          }
          public void mouseEntered(MouseEvent e) {
               label.setIcon(flèche);
         }
     }
  }

so,

               this.modèle.jouer(1);

should fix it :-)
0
zzynxSoftware engineerCommented:
You could be right, Tim
0
TimYatesCommented:
/me does a dance

;-)
0
zzynxSoftware engineerCommented:
...although he's explicitely telling us:

//In the Constructor            <<<<<<<<<<<<<<<<<<<
this.modèle = modèle;
0
TimYatesCommented:
yeah...maybe all the other code in in the constructor too?
0
zzynxSoftware engineerCommented:
Mmmmmaybe ;°)
Matthew016, your input is needed!
0
matthew016Author Commented:
Here I am ! I was eating ! you guys are fast ! :p

CEHJ -> you need to declare any variables of its parent you want to access as final
not agree because
i can acces label and I declared label ->
public class PanelPlateau implements ActionListener{
      private JPanel pNord;
      private JPanel pCentre;
      private JPanel [] pColonne;
      private ImageIcon flèche;
      private ImageIcon spacer;
      private JLabel label;
      private Puissance4 modèle;
just like modèle ...

TimYates -> this.modèle. ...
doesnt work, i get as error "change to 'modèle' "

Here here is some more of my code :




0
TimYatesCommented:
> Here here is some more of my code :

where? ;-)
0
matthew016Author Commented:
public PanelPlateau(Puissance4 modèle) {
     this.modèle = modèle;
     flèche = new ImageIcon("images/down.gif");
     spacer = new ImageIcon("images/spacer2.gif");
     label = new JLabel(spacer);
            
     pNord = new JPanel(new GridLayout (1,7));
     for (int i = 0; i < 7; ++i) {
          pNord.add(pColonne[i]);
          pColonne[i].add(label);
          pColonne[i].addMouseListener( new MouseListener(){
               public void mouseClicked(MouseEvent e) {
                    try {
                         this.modèle.jouer(1);
                    } catch (ColonnePleineException ex) {
                    // TODO Auto-generated catch block
                         ex.printStackTrace();
                    }
               }
               public void mouseEntered(MouseEvent e) {
                    label.setIcon(flèche);
               }
               public void mouseExited(MouseEvent e) {
                    label.setIcon(spacer);                  
               }
               public void mousePressed(MouseEvent e) {}
               public void mouseReleased(MouseEvent e) {}
      
          });
     }
..............
0
CEHJCommented:
label in this case is not a local variable. The solution is as i mentioned
0
matthew016Author Commented:
Sorry but I dont get it, modèle is not a local variable either ...
0
TimYatesCommented:
Whoops:

                     PanelPlateau.this.modèle.jouer(1);

Sorry :-)
0
TimYatesCommented:
You pass a variable called "modèle" in the constructor...  The anonymous inner class is trying to use this variable, NOT the modèle variable in the class (this.modèle)...

either

a)  Change the constructor to:

 public PanelPlateau(Puissance4 m) {
     this.modèle = m;
 
b)  Change the constructor to:

 public PanelPlateau(final Puissance4 modèle) {
     this.modèle = modèle;
 
c)  Change the inner class to:

               public void mouseClicked(MouseEvent e) {
                    try {
                         PanelPlateau.this.modèle.jouer(1);
 
d)  Write a proper MouseListener class (like CEHJ said)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
TimYatesCommented:
NB:  Those were in no particular order...  I'd probably do (b)  because it's the easiest...  But I have been know to do (a), (b), or (d) :-)
0
CEHJCommented:
Using d) will also give you the advantage of making your generated code cleaner and therefore easier to package
0
matthew016Author Commented:
Thanks, can u tell me how i can acces the integer 'i' in the for ?
(i used method c :-))
Because PanelPlateau.this.modèle.jouer(1);
should be PanelPlateau.this.modèle.jouer(i);
Hum I didnt ask that question at start sorry, but do you know how ?

0
matthew016Author Commented:
Hmmm i'll change to d then ...
0
TimYatesCommented:
I *think* you should be able to do:

        for (int i = 0; i < 7; ++i) {
          final int cnt = i ;
          pNord.add(pColonne[i]);
          pColonne[i].add(label);
          pColonne[i].addMouseListener( new MouseListener(){
               public void mouseClicked(MouseEvent e) {
                    try {
                          PanelPlateau.this.modèle.jouer( cnt );
                    } catch (ColonnePleineException ex) {
                    // TODO Auto-generated catch block
                         ex.printStackTrace();
                    }
               }
               public void mouseEntered(MouseEvent e) {
                    label.setIcon(flèche);
               }
               public void mouseExited(MouseEvent e) {
                    label.setIcon(spacer);              
               }
               public void mousePressed(MouseEvent e) {}
               public void mouseReleased(MouseEvent e) {}
     
          });
     }
0
zzynxSoftware engineerCommented:
class PlayerListener extends MouseAdapter {

      private int toPlay = 0;

     public PlayerListener(int i) {
        toPlay = i;
     }

     public void mouseClicked(MouseEvent e) {
          modèle.jouer(toPlay);
     }
     
     public void mouseEntered(MouseEvent e) {
          label.setIcon(flèche);
     }
}
0
zzynxSoftware engineerCommented:
And then of course:

pColonne[i].addMouseListener(new PlayerListener(i));
0
matthew016Author Commented:
Thanks Very Good !!
But i'll need to put modèle and also flèche AND label in the PlayerListener Constructor because i make a seperate class ...
0
matthew016Author Commented:
or not ?
0
TimYatesCommented:
Yup.  Or you can put this class inside your PanelPlateau class...  then you don't have to ;-)

public class PanelPlateau extends whatever
{
    class PlayerListener extends MouseAdapter
    {
        private int toPlay = 0;

       public PlayerListener(int i) {
          toPlay = i;
       }

       public void mouseClicked(MouseEvent e) {
            modèle.jouer(toPlay);
       }
     
       public void mouseEntered(MouseEvent e) {
            label.setIcon(flèche);
       }
    }

... rest of PanelPlateau class

}
0
zzynxSoftware engineerCommented:
>> But i'll need to put modèle and also flèche AND label in the PlayerListener Constructor because i make a seperate class ...
You can pass it afterwards too:

PlayerListener pl = new PlayerListener(i);
pl.setWhatever(whateveryoulike);
pl.setWhatever2(whateveryoulike2);
...
pColonne[i].addMouseListener(pl);
0
zzynxSoftware engineerCommented:
Of course then you have to add the needed functions to your PlayerListener class

e.g. I added setLabel():

class PlayerListener extends MouseAdapter {

      private int toPlay = 0;
      private JLabel theLabel;

     public PlayerListener(int i) {
        toPlay = i;
     }

     public void setLabel(JLabel lbl) {
       theLabel = lbl;
     }

     public void mouseClicked(MouseEvent e) {
          modèle.jouer(toPlay);
     }
     
     public void mouseEntered(MouseEvent e) {
          label.setIcon(flèche);
     }
}
0
CEHJCommented:
You don't necessarily have to go from an anonymous inner class to a stand-alone inner class with its own instance variables. Ask yourself how truly independent of its parent it should be. Certainly it wasn't going to be in the first place ;-)

0
matthew016Author Commented:
Well, I tried it with a named inner class ...
but I still have to put
PanelPlateau.this.modèle.jouer(1) ...

I get an error on modèle.jouer(1)
and also on this.modèle.jouer(1)
0
zzynxSoftware engineerCommented:
Sorry replace

    label.setIcon(flèche);

by
   
    theLabel.setIcon(flèche);

in the above
0
TimYatesCommented:
post your code as it is currently,

You've done something wrong :-(
0
matthew016Author Commented:
Exactly, I answered to fast, forgot the try catch ....
Now it works,
thanks to you three

*splitting points*
not much sorry those are my last one!

Goodbye
0
zzynxSoftware engineerCommented:
Thank you :)
0
CEHJCommented:
8-)
0
TimYatesCommented:
:-)  Good luck!! :-)

Tim
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.