FrankelStein
FrankelStein

Reputation: 1010

Improve communication between JFrame and JPanel

I am working on a small game that needs communication between the main JFrame and a JPanel called gamepan.

the game requires that the user finds a hidden word by clicking on buttons that contains alphabet letters.

My JFrame Contains the gamepan, scorepan,menus and other stuff...

my gamepan contains my buttonsArrayListener, the hidden word and other stuff...

the problem is, when the user finds the hidden word I need to tell my JFrame that he did so this later can repaint the gamepan, make a new word ....

what I did is : I added a boolean in my gamepan that tells if my word is found or not and a MouseListener to my gamepan, so everytime I move the mouse the JFrame tests if the word is found or not then added setters in my gamepan that I use from the JFrame to initialise things again if the hidden word if found.

I find that this is not verry effective to add a MouseListener since I have to mouve the mouse to make the change, and everytime the mouse moves useless treatements are made ...

I want to know if there is a better sollution than adding a MouseListener ?? and I want to know also if I did good to add setters to the gamepan to set its variables for a new word.

Here is my code

gamepan code

public class GamePanel extends JPanel{
private JPanel leftPan = new JPanel();
private JPanel rightPan = new JPanel();
private String[] letters =     {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",};
private JButton Button[] = new JButton[26];

private JLabel label1;
private JLabel label2;
private JLabel label3;
private ActionListener buttonListener;
private JOptionPane jop = new JOptionPane();

private Word randWord = new Word(); // mot aléatoire
private TreatedWord tWord = new TreatedWord(randWord.getRandWord());// mot  aléatoire traité ( etoiles et tout ça )
private char clickedButton;// lettre tappée
private boolean motTrouvé = false; // pour informer la classe Fenetre si le mot a été retrouvé ou pas on utilise ce boolean avec son getter et setter ( a savoir que cette classe est informée si le mot est trouvé ou pas via l'objet tWord)


private final List<CustomListener> customListener = new LinkedList<>(); //On crée une liste de CustomListener pour en ajouter autant qu'on veut(Via addCustomListener)

public GamePanel(){
    this.setBackground(Color.white);
    initGamePan();
    initListeners();
    this.setLayout(new BorderLayout());
    this.add(leftPan,BorderLayout.WEST);
    this.add(rightPan,BorderLayout.EAST);
}

public void initGamePan(){
    rightPan.add(new JLabel(new ImageIcon("131869.jpg")));
    label1 = new JLabel("Nombre de mots trouvés : 0");
    label1.setHorizontalAlignment(JLabel.CENTER);
    label1.setFont(new Font("arial",Font.BOLD,20));
    label1.setPreferredSize(new Dimension(300,50));

    label2 = new JLabel("Score Actuel : 0 point");
    label2.setHorizontalAlignment(JLabel.CENTER);
    label2.setFont(new Font("arial",Font.BOLD,20));
    label2.setPreferredSize(new Dimension(300,50));

    label3 = new JLabel(tWord.getStars());
    label3.setHorizontalAlignment(JLabel.CENTER);
    label3.setFont(new Font("arial",Font.BOLD,30));
    label3.setForeground(Color.blue);
    label3.setPreferredSize(new Dimension(450,50));

    leftPan.add(label1);
    leftPan.add(label2);
    leftPan.add(label3);
    for(int i=0;i<letters.length;i++){
        Button[i]= new JButton(letters[i]);
        leftPan.add(Button[i]);
    }

    leftPan.setPreferredSize(new Dimension(460,650));
    leftPan.setBackground(Color.WHITE);
    rightPan.setPreferredSize(new Dimension(420,650));
    rightPan.setBackground(Color.WHITE);
}

public void initListeners(){
    buttonListener= new ActionListener(){

        public void actionPerformed(ActionEvent arg0) {
            clickedButton = ((JButton)(arg0.getSource())).getText().charAt(0); // on prend le bouton cliqué, on le convertis en string puis en char
            label3.setText(tWord.treatedWord(clickedButton));// on donne a la methode tretedWord de l'objet tWord le char clickedbutton pour faire le traitement sur le mot mystère
            ((JButton)(arg0.getSource())).setEnabled(false);

            if(tWord.isFound()==true){
                jop.showMessageDialog(null, "Bravo t'a trouvé le mot !", "U don't Say B|", JOptionPane.INFORMATION_MESSAGE);
                motTrouvé = true;

            }
        }

    };
    for(int i=0;i<letters.length;i++){
        Button[i].addActionListener(buttonListener);
    }

}


public void setNewWord(){
    this.randWord = new Word();
    this.tWord = new TreatedWord(randWord.getRandWord());
    this.label3.setText(tWord.getStars());
}
public void resetButtons(){
    for(JButton B : this.Button){
        B.setEnabled(true);
    }
}


 public void addCustomListener(final CustomListener listener) {
        this.customListener.add(listener);
    }

 public void notifyWordFound(/* any data you could use */) {
        for(final CustomListener listener : this.customListener) {
            listener.wordFound(/* any data you could use */);
        }
    }

}

MyJFrame code:

public class Fenetre extends JFrame {

    private JMenuBar menu = new JMenuBar();
    private JMenu file = new JMenu("Fichier");
    private JMenuItem neew = new JMenuItem("Nouveau");
    private JMenuItem score = new JMenuItem("Score");
    private JMenuItem quit = new JMenuItem("Quitter");
    private JMenu about = new JMenu("About");
    private JMenuItem how = new JMenuItem("Règles");
    private JMenuItem who = new JMenuItem("Credit");
    private int i=1;
    private ScorePanel scorepan = new ScorePanel(900,650);
    private ReglesJeuPanel rgpan = new ReglesJeuPanel(900,650);
    private GamePanel gamepan = new GamePanel();
    private JPanel pan = new JPanel();
    private JPanel container = new JPanel();
    private JLabel label = new JLabel("------------------------SAMAIKOM------------------------");
    private JTextArea texte = new JTextArea(    "Vous avez sept coups pour trouver le mot caché. Si vous réussissez, on recommence !\n" +
            "Plus vous trouvez de mots, plus votre score augmente. Alors, à vous de jouer !\n" +
            "Proverbe :\t« Pas vu, pas pris !\n" +
                "\tPris ! PENDU ! »");
public Fenetre(){
    this.setTitle("Le Pendu ...");
    this.setSize(900, 650);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    this.setVisible(true);
    initMenu();
    initAcceuilPan();
    initListeners();
    this.setContentPane(container);
}

private void initMenu(){
    file.add(neew);
    file.add(score);
    file.addSeparator();
    file.add(quit);
    file.setMnemonic('F');
    neew.setMnemonic('N');
    neew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,KeyEvent.CTRL_DOWN_MASK));
    score.setMnemonic('S');
    score.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,KeyEvent.CTRL_DOWN_MASK));
    quit.setMnemonic('Q');
    quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,KeyEvent.CTRL_DOWN_MASK));

    about.add(how);
    about.addSeparator();
    about.add(who);
    about.setMnemonic('A');
    how.setMnemonic('R');
    how.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,KeyEvent.CTRL_DOWN_MASK));
    who.setMnemonic('C');
    who.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,KeyEvent.CTRL_DOWN_MASK));

    menu.add(file);
    menu.add(about);
    this.setJMenuBar(menu);
}

private void initListeners(){
    score.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent arg0) {
            container.removeAll();
            container.add(scorepan);
        }
    });
    quit.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent arg0) {
            System.exit(0);
        }
    });
    how.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent arg0) {
            container.removeAll();
            container.add(rgpan);
        }
    });
    neew.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent arg0) {
            gamepan.setNewWord();
            gamepan.resetButtons();
            container.removeAll();
            container.add(gamepan);
        }
    });

    gamepan.addCustomListener(new CustomListener(){

        public void wordFound() {
        }

    });

    gamepan.notifyWordFound();       // where to put this ?????


}

private void initAcceuilPan(){
    pan.setBackground(Color.white);
    pan.add(new JLabel(new ImageIcon("131868.jpg")));
    texte.setEditable(false);
    Font F1 = new Font("arial",Font.BOLD,20);
    Font F2 = new Font("arial",Font.BOLD,15);
    label.setFont(F1);
    texte.setFont(F2);
    container.setBackground(Color.white);
    container.add(label);
    container.add(pan);
    container.add(texte);
    //container.add(gamepan);

}


public static void main(String[] args) {
    Fenetre F1 = new Fenetre();
}

}

Upvotes: 0

Views: 268

Answers (2)

ccjmne
ccjmne

Reputation: 9606

In general, the ClassName.this syntax is used inside of a nested class that is not static. It is used to access its outer class's instance. Let me give you an example:

class OuterClass {
    private final String text = "I'm the outer class!";

    class NestedClass {
        private final String text = "I'm the nested class!";

        public final String getText() {
            return this.text;  // "I'm the outer class!"
        }

        public final String getOuterClassText() {
            return OuterClass.this.text;  // "I'm the nested class!"
        }
    }
}

Now, in your case, the nested class you have is actually an anonymous class you created by instantiating the MyEventListener interface, with the following code:

gamePanel.addMyEventListener(new MyEventListener() {
    @Override
    public void wordFound(/* any data you could use */) {
        // Here, access your GamePanel's instance attributes and methods using GamePanel.this
    }
});

Let me explain to you what the above code exactly did:

new MyEventListener() {
}

This notation will create an anonymous class that implements MyEventListener. You can modify that class definition by putting anything you want between the brackets {}. Since you implement some interface, you have to override every abstract method declared in that interface, like this:

new MyEventListener() {
    @Override
    public void wordFound(/* any data you could use */) {
    }
}

I hope it's clear and it helped you :)

Upvotes: 0

ccjmne
ccjmne

Reputation: 9606

You could use some custom Event that can occur when a word is found:

public interface MyEventListener {
    public abstract void wordFound(/* any data you could use */);
}

Then make your GamePan capable of emitting such events:

public class GamePan extends JPanel {
    private final List<MyEventListener> myEventListeners = new LinkedList<>();

    // Here, keep everything you already have

    public void addMyEventListener(final MyEventListener listener) {
        this.myEventListeners.add(listener);
    }

    private void notifyWordFound(/* any data you could use */) {
        for(final MyEventListener listener : this.myEventListeners) {
            listener.wordFound(/* any data you could use */)
        }
    }
}

When the word is found, just call GamePan#notifyWordFound. Then, register some updating method to be called in your JFrame when such an event occurs:

public class MyJFrame extends JFrame {
    // Here, keep everything you already have

    public JFrame() {
        // Here, keep everything you already have

        // Let's assume your ScorePanel instance is here:
        final ScorePanel scorePanel = new ScorePanel();

        this.gamePan.addMyEventListener(new MyEventListener() {
            @Override
            public void wordFound(/* any data you could use */) {
                // Update your application using any data you can use :)
                scorePanel.wordFound(/* any data you could use */);
            }
        });
    }
}

Here, we simply call the ScorePanel#wordFound method so the ScorePanel can be updated.

Don't forget that you can transmit any data you're interested in through all these methods. For example, if you want to transmit the word the user just found, the MyEventListener#wordFound method could be declared as follows:

public interface MyEventListener {
    public abstract void wordFound(final String word);
}

EDIT: Added some interaction with a ScorePanel instance to answer your additional question in comments :)

Upvotes: 4

Related Questions