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

AWT/Swing Java Discussion :

[JPanel] input clavier


Sujet :

AWT/Swing Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2005
    Messages : 112
    Par défaut [JPanel] input clavier
    Bonjour à tous,
    J'ai un tout petit projet informatique à faire pour les cours : un jeu de domino!
    Aimant bien le Java et n'ayant pas souvent l'occasion d'en faire, je me suis dis que c'était l'occasion de m'y remettre!
    J'ai installé eclipse 3.2 (le bonheur!! ) puis j'ai coder un petit jeu de domino sans interface graphique avec juste un texte afficher sur la console et une gestion des input clavier avec un BufferedReader.
    Jusque la tous va bien!!
    Mais j'ai voulu rajouter une petite interface graphique pour afficher un semblant de domino (des rectangles avec des chiffres dedans), alors j'ai pris le code de ce tutorial :

    tuto

    Que j'ai adapté à mon jeu.
    Malheuresement, comme mon jeu est une boule de type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    while(!myGame.EndOfGame())
    {
            //actualisation du jeu
    }
    Ma fenetre JCanvas bug à l'affichage car elle n'est pas réactualisée!
    Alors, je me suis dis qu'il fallait que je créé un thread à part pour la boucle de mon jeu, ce que j'ai fais... Mais avec le même résultat!

    Donc, ma question est simple (malgrès la longeur de ce post ) :

    comment gérer l'affichage d'un JCanvas tout en gérant une boucle de jeu qui prend des input clavier?

    Ca peu vous paraître simple, mais je n'ai pas trouver de solutions actuellement.

    Merci d'avance pour votre aide,
    A bientot,

    dede

  2. #2
    Membre chevronné Avatar de spekal
    Inscrit en
    Mai 2005
    Messages
    502
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 502
    Par défaut
    Méfie-toi que JCanvas n'évoque pas grand chose : c'est juste le nom d'une classe dans l'exemple sur lequel tu travailles.

    Concernant ton problème, il faut effectivement travailler sur les threads. Ta particularité est que tu souhaites entrer des évènements clavier depuis une console, ce qui est un excellent exercice ; cependant, usuellement, les évènements clavier arrivent par le GUI lui même, par l'intermédiaire d'un champ de formulaire, par exemple, et il n'y a pas ce souci de thread ; mais il y en a d'autres.

    Il existe toujours un thread réservé à swing, créé par la mécanique swing. Toi, tu lis, probablement, le clavier depuis un thread à toi. Pour faire une mise à jour de l'affichage depuis le thread clavier il faut utiliser SwingUtilities.invokeAndLater, ou invokeAndWait.

    Des infos sur tout ça dans How to Use Threads (avec swing).

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2005
    Messages : 112
    Par défaut
    Méfie-toi que JCanvas n'évoque pas grand chose : c'est juste le nom d'une classe dans l'exemple sur lequel tu travailles.
    Oui, en effet exuse moi, j'implémente en fait la classe JPanel...
    D'ailleurs, tu me parles Swing, mais la classe JPanel ne fait pas partie de swing non? Mais je peux tout de même utiliser un thread swing c'est ça?

    Sinon, pour gérer les évènements clavier avec mon Panel, il faut que je créer un Listener non? J'avais fait ca pour un paint qui gérer la souris, mais justement je voulais pas faire quelquechose de trop compliqué pour ce programme,mais bon je vais peut-être revenir la dessus.

    Je vais tester les input clavier avec tes fonctions swing et si ca marche, je pense que j'irai pas plus loin .

    En tout cas merci pour ta réponse.

    A+

    dede

    P.S : ton avatar ça serait pas une photo de ce que l'on appel les "chemtrail"?

  4. #4
    Membre chevronné Avatar de spekal
    Inscrit en
    Mai 2005
    Messages
    502
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 502
    Par défaut
    Citation Envoyé par dedesite
    P.S : ton avatar ça serait pas une photo de ce que l'on appel les "chemtrail"?
    Non, c'est une toute petite partie de ça.

    Bon, maintenant, et toi, est-ce que tu peux me dire ce qu'est un chemtrail ?

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2005
    Messages : 112
    Par défaut
    Les chemtrails sont des trainées d'avion qui apparement serait un peu spéciales... Tout ça fait partie d'une vaste théorie du complot très controversée, j'ai pas vraiment d'avis la-dessus, mais je me suis un peu informé, je dois dire que c'est bizarre, mais de la à dire que c'est vrai...

    liens wikipédia

    A+

    dede

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2005
    Messages : 112
    Par défaut
    En fait, je vois pas vraiment comment prendre des input clavier avec la fonction invokeAndWait ou invokeAndLater ?
    Ces fonctions servent en fait à créer un thread où l'on executerais une fonction passée en paramètre c'est ça?
    J'ai essayé de lui passé ma fonction où je prenais mes inputs clavier mais l'application à plantée...
    Puis de toute façon il reste toujours ma boucle "interminable" que constitue la boucle principale du jeu, elle bloquera toujours le thread d'affichage celle la non?
    Je comprend pas pourquoi le fait de mettre toute cette boucle dans un thread a part n'a pas fonctionner?
    Enfin bref, je me rend compte que y'a pleins de truc en Java que je connais pas et que c'est un peu plus compliqué que je ne le pensais... Dommage moi qui voulait faire un truc sympa. J'ai pas le temps de regarder en détails toutes ces choses, ma prof devra se contenter d'un jeu sur console (text hein pas console de salon ) si je ne trouve pas une solution d'ici demain.

    A+
    dede

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 913
    Billets dans le blog
    54
    Par défaut
    Essaie de voir sur les forums de http://javagaming.org/ (en anglais) qui sont plus specialises dans le devel de jeux.

    Sinon, je ne comprend pas trop bien le probleme et la reponse suggeree par spekal : a priori si tu as un interface graphique, tu ne vas probablement plus saisir tes commandes sur la console, non ?

    Les evenements claviers sur un JPanel sont de type evenentiels, tu n'as pas a creer de boucle ou de thread. Elle existe deja c'est l'EDT, il te faudra juste appeler repaint() apres avoir effectuer une action dans ton jeu histoire de rafraichir l'affichage.

    Par contre tu peux effectivement avoir besoin d'une autre thread pour faire un timer interne au jeu (pour faire un chronometre par exemple). Encore que dans le cas d'un jeu de domino, qui est un jeu simple, je trouve ca un peu inutile : un Timer Swing qui se repete intervalle regulier peut tres bien servir a rafraichir l'horloge (mais dans ce cas ca lie ton jeu fortement a Swing).

    Pour pouvoir capturer les evenement clavier dans un JPanel il suffit :
    - d'ajouter un KeyListener qui traite les touches utilisees.
    - de rendre le JPanel focusable (setFocusable(true)).
    - de lui donner le focus (requestFocus(true)).

    Sinon dans l'absolu, tu as probablement (et suite a l'utilisation du totu) un probleme de conception de ton jeu : ton jeu est lie a cette boucle sur les entrees clavier et c'est mal. En theorie, il te faudra faire plus d'abstraction et separer le moteur de ton jeu de ton affichage et de ton interface de controle, ce qui te permettrai de reutiliser ce moteur avec des affichages et controles differents (console, Swing, SWT, web, ....). Dans ce cas oui, le moteur du jeu devrait constituer une entite bien distincte a lui tout-seul qui peut eventuellement necessiter l'utilisation de threads. Cependant en pratique pour quelques chose d'aussi simple qu'un jeu de domino, et surtout si tu debutes en Java, il n'est pas necessaire de se casser trop la tete sur ce genre de choses (tout en les gardant a l'esprit pour plus tard).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2005
    Messages : 112
    Par défaut
    Salut bouye,
    merci pour ta réponse!! Ca me conviens mieux comme explication!
    Je savais bien qu'il fallait gérer les évènements avec un listener pour un JPanel, mais justement j'avais fait mon jeu totalement a part de l'affichage (le tuto ne m'a servis que pour l'affichage) et comme j'utilisais la console pour raison de simplicité, je ne voulais pas trop me prendre la tête et juste avoir un affichage qui concordait avec ce que la console affichait...
    En fait, la ce que tu me dis c'est que je pourrai mettre la méthode repaint dans ma boucle de jeu et gérer les évènements clavier avec le KeyListener?

    Il faudrait alors que je modifier l'affichage pour que les consignes du jeu ne s'effectuent plus sur la console mais dans mon JPanel... Ou alors que je rajoute simplement quelques affichages sur le JPanel (car il ne sont pas tous nécessaire). En fait, mon moteur de jeu n'est pas séparé de l'affichage console, mais bon c'est pas vraiment un affichage...

    En tout cas merci de ton aide, j'èspère que j'ai bien compris ce que tu as dis.

    A+

    dede

  9. #9
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 913
    Billets dans le blog
    54
    Par défaut
    Le but est d'utiliser un modele de conception proche du pattern Observer ou du modele MVC (model-view-controler/modele-vue-controlleur). Ton moteur jeu est un "modele" et ton interface graphique ou console est une "vue + controlleur". Le controlleur fait passer des actions au modele qui se modifie en consequence et informe la vue qu'elle doit se mettre a jour, etc...

    De maniere simple, ton panel ne fait rien d'autre que de l'affichage et un traitement des touches claviers. Si ton jeu est plus complexe, ta vue peut aussi contenir et manipuler des versions/representations graphiques des objets (en general non-graphiques*) manipules par le moteur de jeu. Dans le cas de "gros" jeux (ex shooter, MMORPG), la vue (on parle aussi de partie "cliente") peut eventuellement utiliser le reseau pour contacter le modele/moteur de jeu (ou partie "serveur"). Egalement dans des jeux du genre Doom, Quake etc... meme quand tu joues seul en local sur ton ordi, tu as une partie cliente connectee a une partie serveur. Certains clients embarquent egalement une partie de la logique serveur ce qui permet entre autre de faire de la prediction de mouvements pour compenser le lag par exemple.

    Mais bon je suis peut-etre partie un peu loin, un peu vite d'autant plus que tu es tout au debut et que tu n'as pas forcement de partie reseau dans ton jeu (cependant le principe reste similaire le moteur du jeu est relativement decouple de l'affichage). N'oublie pas que je t'ai indique un forum specialise dans les jeux ou tu trouveras plus d'informations (et egalement des corrections si jamais je t'ai dit des betises).

    * Des jeux 2D ou 3D peuvent necessiter que le moteur de jeu connaisse certaines informations comme la position, la surface, le volume, etc... cependant.

    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
    public class DominoPanel extends JPanel implements KeyListener {
      /** The game engine.
      */
      private DominoGame game = ...
     
      /** Creates a new instance.
      */
      public DominoPanel() {
        ...
        setFocusable(true);
        requestFocus(true);
        addKeyListener(this);
        ...
      }
     
      /** @inheritDoc
      */
      @Override protected void paintComponent() {
         ...
      }
     
      /** @inheritDoc
      */
      public void keyPressed(KeyEvent event) {
         switch (event.getKeyCode()) { 
            ...
            case KeyEvent.VK_XXXXXXXXX: { 
               game.doWhateverShouldBeDoneForSuchAction();
            }
            break;
            ...
         }
         repaint();
      }
    }
    Tu peux aussi faire que ton jeu soit un generateur d'evenements, histoire de mettre a jour ses differentes vue quand quelques chose d'important a modifie l'etat du jeu.

    Note : les methodes indiquees ici sont bidons, de base une seule methode suffit pour indiquer qu'un changement a eut lieu et que la vue doit etre mise-a-jour. Apres tu peux en creer des specifiques pour indiquer des notifications d'evenements bien precis. Egalement plutot que de creer de nombreuses methodes differentes tu peux utiliser un objet Event dont l'etat varie en fonction du changement qui a eut lieu (de maniere similare a ce que Swing/AWT utilise) :

    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
    interface DominoListener {
      /** New game has started.
       */
      public void gameStarted();
     
      /** The state of the game has changed.
       * <br>i.e.: a new piece has been added to the domino board.
       */
      public void gameStateChanged();
     
      /** Game has been lost.
       */
      public void gameLost();
     
      /** Game has been won.
       */
      public void gameWon();
    }
    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
    public class DominoGame {
       /** Adds a listener interrested into receiving game events.
        * @param listener The listener to be added.
        */
       public void addDominoListener(DominoListener  listener) {
         ...
       }
     
       /** Removes a listener interrested into receiving game events.
        * @param listener The listener to be removed.
        */
       public void removeDominoListener(DominoListener  listener) {
        ...
       }
     
       /** Fire a game started event to all registered listeners.
        */
       protected void fireGameStarted() { 
         for (DominoListener aListener : listenerList) {
            aListener.gameStarted();
          }
       }
     
      ...
    }
    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
     
    public class DominoPanel extends JPanel implements KeyListener, DominoListener {
      ...
     
      game.addDominoListener(this);
     
      ...
     
      /** @inheritDoc
      */
      public void gameWon() { 
        JOptionPane.show.........
      }
     
      ...
    }
    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
     
    public class DominoConsole implements DominoListener  {
      /** The game engine.
      */
      private DominoGame game = ...
     
      ...
     
      game.addDominoListener(this);
     
      ...
     
      while (true) {
         ....
         if (xxxxxxxxxx.equals(command.toLowerCase())) {
           game.doWhateverShouldBeDoneForSuchAction();
         }
         else if ("q".equals(command.toLowerCase())) { 
           game.removeDominoListener(this);
           System.out.println("Bye bye!");
           System.exit(0);
         }     
      }
     
      /** @inheritDoc
      */
      public void gameWon() { 
        System.out.println("Congratulation, you won!");
      }
      ...
    }
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2005
    Messages : 112
    Par défaut
    Waou, ca c'est une réponse bouye!!!

    Je me sens un peu géné de t'avoir fait "perdre" ton temps car d'une part j'ai rendu mon projet aujourd'hui et d'autre part je programme des jeux depuis pas mal de temps en C++ (j'ai une licence pro en imagerie numérique).
    Donc en fait c'est pas trop que j'avais pas les compétences, mais plus que je n'avais pas trop le temps de regarder comment faire ça simplement en Java. J'avais pensé que ma méthode était la bonne, j'aurais du utiliser des listener des le début...
    J'avoue que j'ai fais ca sans réfléchir en me disant qu'un domino était quelquechose de tellement simple que j'allais faire ce que je veux en 2 sec... J'aurais du faire une petite partie d'analyse tout de même... Ca m'apprendra à me croire plus intelligent que je le suis!

    En tout cas merci pour votre aide (et le site), la prochaine fois que je voudrais faire un jeu en Java je réfléchirai un peu plus c'est promis .
    Mais bon, je vais retourner dans les méandres du C++ et faire des mes jeux avec un langage de script peut-etre.

    A bientot,

    dede

  11. #11
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 913
    Billets dans le blog
    54
    Par défaut
    Ce n'est pas grave et c'est bon de garder ca en tete pour la suite.

    Mais je te ressure, 8 ans apres mon DESS de Genie Logiciel je me rend compte que j'ai pas mal perdu mes concepts de base durement (?! heuh ) apris (me suis plante dans certains topics recents dont celui sur les fabriques abstraites notamment). Cela vient du fait que pour mon boulot programmant seul en Java je ne peut me permettre de perdre trop de temps a toujours appliquer ces principes (oui je sais c'est mal) ; je les utilises, mais pas partout.

    De meme un rapide sondage en debut d'annee entre les anciens camarades de classe de la promo montre que seuls ceux qui font partit de tres grosses boites ayant de lourds projets avec des equipes concequentes (Thales, EADS, etc... et encore pas toujours, cela depend dans quels services ils sont) mettent en oeuvre ces pratiques (oui je sais c'est encore plus mal).

    Quand tu es seul et que le projet n'est pas enorme, et pas forcement destine a etre reutilise ailleurs ou par quelqu'un d'autre, ces methodes peuvent engendrer un surcout en temps et en energie qui font que les utiliser ne sont pas toujours une bonne idee. Apres tout, une phrase importante dans le livre du gang des 4 (Design Pattern) dit quelque chose du genre "If the pattern gets in the way, get rid of the pattern". Ce sont des conseils de bonne conception/programmation, pas des lois ou des regles ultimes.

    Cependant ce que je t'ai indique ici est tout a fait applicable en C++. En effet, ces concepts ne sont pas du tout lies pour la plupart au language Java. Il se trouve juste que l'API java est plus recente et repose fortement a certains endroits (mais pas partout) sur des patterns et des methodes de conception connues et reconnues. L'API C++ est plus ancienne et herite du C et meme si dans sa version plus recente les STL integrent bien quelques patterns (Iterator), elle est tout de meme trop simpliste/pas assez fournie pour s'en rendre bien compte. Il faut voir du cote des APIs/Framework plus avances (.NET, etc...) pour bien voir apparaitre certains pattern.

    Non-obstant tu peux donc faire ce genre de separations/abstractions dans ton propre code a toi quitte a develloper tes propres libs.

    PS : pense au bouton resolu
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

Discussions similaires

  1. linux, input clavier/souris
    Par kripteks dans le forum C++
    Réponses: 6
    Dernier message: 03/03/2013, 13h04
  2. Réponses: 8
    Dernier message: 15/08/2011, 22h20
  3. Réponses: 2
    Dernier message: 04/08/2010, 23h20
  4. Clavier JPanel JEditor
    Par midotek dans le forum Agents de placement/Fenêtres
    Réponses: 0
    Dernier message: 07/12/2008, 14h22
  5. Input clavier et UNICODE ?
    Par Clad3 dans le forum SDL
    Réponses: 9
    Dernier message: 09/01/2007, 18h43

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