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

Agents de placement/Fenêtres Java Discussion :

Rafraîchir un JFrame


Sujet :

Agents de placement/Fenêtres Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Inscrit en
    Mars 2004
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 7
    Par défaut Rafraîchir un JFrame
    Bonjour à tous,

    Voila, je fais de mon mieux avec mes connaissances Java pour programmer un jeux de cartes multi joueurs en réseau, sur le principe d’un échange client – serveur. Le serveur gère le jeu et centralise les échanges, les clients ne sont que des interfaces avec l’utilisateur.

    J’essaie depuis quelques temps de programmer l’affichage côté client, et j’ai de gros problèmes pour rafraîchir la fenêtre lorsque de nouveaux objets (nouvelles cartes, scores…) sont envoyés par le serveur. Je suis complètement perdu avec l’utilisation de la méthode repaint().

    Ma fenêtre JFrame comporte un Jpanel lui-même divisé en 2 dans lequel je dessine deux classes qui héritent de Jpanel : GameBoard et ChatBoard.

    GameBoard, placé en haut, est le plateau du jeu, la ou sont affichés les cartes et autres infos relatives au jeu. ChatBoard, placée en bas, est simplement composée d’un JTextArea et d’un JTextField pour que les joueurs puissent chatter entre eux.

    J’utilise un BorderLayout pour l’affichage dans GameBoard, et je dessine mes cartes dans le panneau SOUTH du BorderLayout. Les cartes du jeu sont des images au format png, chargés sous forme d’ImageIcon, et affichés dans des Jlabels.

    Le plus simple est peut être de montrer le code, en simplifié :

    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
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
     
    public class ClientFrame extends JFrame implements Observer
    {
    	private GameClientAble theModel;
    	private ChatBoard theChatBoard;
    	private GameBoard theGameBoard;
     
     
    	public ClientFrame(GameClientAble theModel)
    	{
    		super();
     
    		this.theModel = theModel;		
     
    		jp = new JPanel();					
    		jp.setLayout(new BorderLayout());
     
    		theGameBoard = new GameBoard();
    		theChatBoard = new ChatBoard();		
    		jp.add(theChatBoard, BorderLayout.SOUTH);
    		jp.add(theGameBoard, BorderLayout.CENTER);
     
    		this.add(jp);				
     
    		this.setContentPane(jp);
     
    		this.setVisible(true);
     
    		theModel.addAnObserver(this);
    	}
     
    	// la méthode update est appelée par le modèle lorsq'un nouvel objet arrive
    	public void update(Observable obs,Object o)	{
     
    		Message message = theModel.getInputMessage(); // je récupère le message sur le modèle
     
    		if( (message.getDescription()).equals(Message.CLIENTMESSAGE) || (message.getDescription()).equals(Message.SERVERMESSAGE) ) {
    			theChatBoard.update(message);
    		}
    		else{
    			this.repaint();
    		}
    	}
     
    	private class ChatBoard extends JPanel implements ActionListener 
    	{		
    		private JTextArea ta;
    		private JTextField tf;
     
    		public ChatBoard()	{
    			...
    		}
     
    		public void update(Message message)	{
    			//affiche le message sur le TextArea
    		}
     
    		public void actionPerformed(ActionEvent e) {
    			// informe le modèle qu'un message est pret a être envoyé
    			if (e.getSource().equals(tf)) {
    				theModel.send(new Message(Message.CLIENTMESSAGE, new ClientMessage(theModel.getMyName(),tf.getText())));
    				tf.selectAll();              
    			}
    		}  
    	}
     
    	private class GameBoard extends JPanel {
     
    		private JLabel label;
    		private JPanel clientCardPanel; // le panel sur leque sont dessinés les cartes
     
    		public GameBoard() {
    			createBoard();			
    		}		
     
    		public void createBoard() {
     
    			this.setLayout(new BorderLayout (10,10));
     
    			clientCardPanel = new JPanel(new FlowLayout(FlowLayout.CENTER) ); // le panel sur lequel j'affiche les cartes du joueur
     
    			try {
    				// theDeck est le tas de carte du joueur à dessiner
    				for(int i = 0 ; i != theModel.getTheDeck().size() ; i++) {
     
    					// j'extrais la couleur et le numéro de la carte a afficher que j'enregistre dans un String
    					String file = theModel.getTheDeck().getCard(i).getSuit() + theModel.getTheDeck().getCard(i).getFace();
     
    					clientCardPanel.add(label = createLabel( file ) ); // l'images est chargée et affichée dans un Jlabel
    				}
    				this.add(clientCardPanel, BorderLayout.SOUTH); // je place le panneau de carte dans le Jpanel
    			}
    			catch(Exception e) {				
    			}  
    		}
     
    		public void paint() {
    			createBoard();
    		}
     
    		private JLabel createLabel(String icon){
    			JLabel label = new JLabel(readImageIcon(icon));
    			return label;
    		}
     
    		private ImageIcon readImageIcon(String filename){
     
    			java.net.URL imgURL = GameBoard.class.getResource("images/" + filename + ".png");
     
    			if (imgURL != null) {
    				return new ImageIcon(imgURL);
    			}
    			System.err.println("Couldn't find file: " + filename);
    			return null;
    		}
    	}
    }
    Voila, quand je lance ça, chaque fois qu’un update est appelé par le model, c.a.d qu’un nouveau tas de cartes est à dessiner, rien ne change dans ma fenêtre. Lorsque par contre je redimensionne la fenêtre, je vois apparaître sous le dessin actuel le nouveau dessin avec les nouvelles cartes. Je me doute bien qu’il y à quelque chose qui cloche dans ma façon de redessiner mais je n’arrive pas a trouver comment changer ça.

    Merci pour votre aide
    Bat

  2. #2
    Gfx
    Gfx est déconnecté
    Expert confirmé
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    		public void paint() {
    			createBoard();
    		}
    Cette méthode ne sera jamais appelée car il faut surcharger paint(Graphics) ou paintComponent(Graphics). Mais c'est une mauvaise manière de procéder.

    Remplace l'appel this.repaint() par theGameBoard.createBoard(). Le problème est que dans createBoard() tu ne remplaces pas les composants existants mais tu en ajoutes d'autres. Il faudrait en fait appeler createBoard() *une fois* et garder une liste des labels contenant tes cartes. Ensuite, quand tu dois mettre à jour l'affichage, il te suffira de changer l'image du ou des labels correspondant aux cartes modifiées.

  3. #3
    Nouveau membre du Club
    Inscrit en
    Mars 2004
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 7
    Par défaut
    Salut Romain,

    Merci pour ton aide. Effectivement avec un paint définit comme ça je ne risquais pas d'aller loin.

    J'ai suivis tes conseils, j'ai enlevé ce pseudo paint() et j'ai mis ça à la place :

    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
     
    	private class GameBoard extends JPanel {
     
    		private JLabel label;
    		private JPanel clientCardPanel;
     
    		public GameBoard() {
    			this.setLayout(new BorderLayout (10,10));
    			clientCardPanel = new JPanel(new FlowLayout(FlowLayout.CENTER) ); // le panel sur lequel j'affiche les cartes du joueur
    			drawPlayersCards();
    			this.add(clientCardPanel, BorderLayout.SOUTH); // The Player's panel			
    		}		
     
    		public void drawPlayersCards() {
     
    			clientCardPanel.removeAll(); // j'efface tout
     
    			try {
    				// theDeck fait réfèrence au tas de carte du joueur  dessiner
    				for(int i = 0 ; i != theModel.getTheDeck().size() ; i++) {
     
    					// j'extrais la couleur et le numro de la carte a afficher que j'enregistre dans un String
    					String file = theModel.getTheDeck().getCard(i).getSuit() + theModel.getTheDeck().getCard(i).getFace();
     
    					clientCardPanel.add(label = createLabel( file ) ); // l'images est charge et affiche dans un Jlabel
    				}
     
    			}
    			catch(Exception e) {				
    			}  
    		}
     ...
    }
    et j'appelle cette fonction dans la méthode update de ClientFrame comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public void update(Observable obs,Object o)	{
     
    		Message message = theModel.getInputMessage();
     
    		if( (message.getDescription()).equals(Message.CLIENTMESSAGE) || (message.getDescription()).equals(Message.SERVERMESSAGE) ) {
    			theChatBoard.update(message);
    		}
    		else{
    			theGameBoard.drawPlayersCards();
    		}
    	}
    c'est un peu brutal de tout redessiner mais ça fonctionne presque parfaitement. Je metterais en place un test pour déterminer quelles cartes sont à redessiner plus tard.

    Le seul problème maintenant, c'est que l'affichage des nouvelles cartes ne se fait toujours pas automatiquement. Il faut pour cela que j'agrandisse ou que je réduise ma fenêtre. Et la tout s'affiche comme il faut. Il doit me manquer un appelle à paint() quelque part non ?

  4. #4
    Gfx
    Gfx est déconnecté
    Expert confirmé
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Par défaut
    À la fin de drawPlayerCards() il suffit de mettre :
    clientCardPanel.revalidate();

  5. #5
    Membre chevronné Avatar de broumbroum
    Profil pro
    Inscrit en
    Août 2006
    Messages
    406
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2006
    Messages : 406
    Par défaut
    Citation Envoyé par bapt
    (...)
    Le seul problème maintenant, c'est que l'affichage des nouvelles cartes ne se fait toujours pas automatiquement. Il faut pour cela que j'agrandisse ou que je réduise ma fenêtre. Et la tout s'affiche comme il faut. Il doit me manquer un appelle à paint() quelque part non ?
    Il existe un ContainerListener pour statuer les événements du panel. Tu pourrais faire un callback à paint() ou validate() (ça par exemple! validate...) pour chaque nouvel ajout de carte avec la méthode componentAdded(). Par expérience ça fonctionne nickel.

  6. #6
    Gfx
    Gfx est déconnecté
    Expert confirmé
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Par défaut
    Sûrement pas après chaque ajout. À part demander au layout de faire plein de fois le même travail, ce n'est pas utile. Il suffit de le faire une fois que tout a été enlevé puis remis dans le container. Et nul besoin d'utiliser un listener puisqu'ici on sait exactement quand l'ajout sera fait.

  7. #7
    Membre chevronné Avatar de broumbroum
    Profil pro
    Inscrit en
    Août 2006
    Messages
    406
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2006
    Messages : 406
    Par défaut
    Oui mais l'affichage ne rafraichira pas tout de suite, et c'est évident que les cartes apparaisent par intermittence dans un jeu.


    Je trouve sympas les photos sur ton blog! Vraiment sympa

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. JTextArea et JFrame à actualiser / rafraîchir
    Par Hohenheim dans le forum Agents de placement/Fenêtres
    Réponses: 0
    Dernier message: 31/05/2009, 22h57
  2. [JDialog] JDialog ou JFrame ?
    Par Mister Nono dans le forum Agents de placement/Fenêtres
    Réponses: 2
    Dernier message: 25/04/2004, 22h55
  3. Comment mettre une image en fond de JFrame
    Par marc26 dans le forum Débuter
    Réponses: 3
    Dernier message: 19/01/2004, 18h57
  4. Réponses: 3
    Dernier message: 29/12/2003, 14h47
  5. Faire une JFrame avec LookAndFeel
    Par aburner dans le forum Agents de placement/Fenêtres
    Réponses: 5
    Dernier message: 03/12/2003, 09h54

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