lundi 18 mai 2009

Créateur de boutons

Je me suis programmé un créateur de boutons en Java!! Les boutons sont très utiles. Quand on les clique, ils se désactivent et ne peuvent plus être cliqués. Ce sont donc des once-in-a-lifetime buttons, et j'en profite chaque fois que je clique.

Voyez-vous, la dernière fois que j'avais fait du Java (qui s'adonnait à être la première fois que j'essayais pour vrai les interfaces graphiques), il n'y avait rien qui fonctionnait. D'abord, je me suis aperçu (merci Nicolas) que la machine virtuelle que Eclipse (mon éditeur de code) utilisait fonctionnait très mal (elle ne faisait pas ce que l'on s'attendrait d'elle, bref). Ensuite, j'étais incapable de lancer le programme en console parce que Java demande à ce qu'on nomme le programme sans en donner l'extension ".class" (ce qui est contre-intuitif, je trouve).

Les deux problèmes réglés, et mon code qui fonctionnait finalement, j'ai pu continuer (depuis hier) mon avancement certain dans ce monde compliqué pour rien des interfaces graphiques en Java.


Notion d'évènement

Vous savez ce qu'est la programmation évènementielle? En gros, quand quelque chose se passe (un bouton est cliqué, une fenêtre est cliquée, un choix d'un combo box est changé, ...), ça s'appelle un évènement. Habituellement, c'est sans intérêt, mais en Java, un bouton cliqué devient une épopée.

En effet, il y a dissociation assez intéressante entre "composant" (un bouton, par exemple) et "évènement" (le bouton est cliqué). En fait, il faut développer et munir ledit bouton d'un écouteur d'évènement, dont la seule raison d'être est de faire quelque chose quand le bouton est cliqué. Le problème (peu apparent pour le moment) est lié à l'encapsulation des trucs, c'est-à-dire les accès refusés des classes à des éléments en dehors de ces classes. Concrètement, cela veut dire par exemple qu'un écouteur pourra déterminer qu'un bouton a été cliqué, mais ne saura pas lequel (à moins qu'on lui fournisse cette donnée-là en argument, d'où le fait que ça devient laborieux).

Bref, je m'évade et m'éloigne, mais je me suis créé un mini programme qui est muni initialement de deux choses: une fenêtre (d'uh) et un bouton qui s'appelle "Créer des boutons". Ce bouton crée des boutons (3 à la fois). Finalement, ces derniers, lorsque cliqués, se désactivent (ils ne font rien, bref). La fenêtre, quant à elle, est munie d'un écouteur qui fait que quand je clique dans la fenêtre, les coordonnées relatives du clic sont affichées.

Voici quelques images montrant le programme en pleine exécution:











Pour les intéressés SEULEMENT

Avant de me faire lancer des pierres, je vous avertis: ce qui suit n'intéressera personne, à moins que vous vouliez voir un peu de code source. En clair, si ça ne vous intéresse pas, arrêtez de lire, parce que vous allez m'haïr plus qu'autre chose.


Voici un peu comment le programme a été écrit. J'ai quatre classes: la classe principale, la classe qui sert à créer une fenêtre qui comprend le bouton initial, et deux classes qui servent simplement d'écouteurs (un écouteur pour le bouton "Créer des boutons", un écouteur pour les autres boutons (ceux qui se désactivent)).

La classe principale instancie un objet de type FenetreCreerBoutons, instanciation faite grâce au code suivant:

public FenetreCreerBoutons() { //constructeur

setTitle("Wo0t!");
setSize(150,600);
addMouseListener(this);
creerBoutons = new JButton("Créer des boutons");
Container contenu = getContentPane();
contenu.setLayout(new FlowLayout());
contenu.add(creerBoutons);
creerBoutons.addActionListener(new EcouteCreer(contenu));

}

Le code
addMouseListener(this)
signifie que la fenêtre sera son propre écouteur d'évènement. En gros, dans cette même classe, j'ai défini des méthodes qui gèrent ces évènements. La variable "contenu" (de type Container) représente seulement le contenu de la fenêtre; quand je mets
contenu.add(creerBoutons);
ça veut dire que je rajoute le bouton créé dans la fenêtre. Ensuite, la ligne
creerBoutons.addActionListener(new EcouteCreer(contenu));
signifie que ce bouton a un écouteur d'évènement de type EcouteCreer, qui nécessite un argument d'instanciation, à savoir le contenu de la fenêtre (argument qui sert à savoir où placer les nouveaux boutons créés).

La classe EcouteCreer (qui sert à créer des écouteurs) permet d'exécuter le code suivant lorsque le bouton est cliqué:

for (int i=1;i<=3;i++) {

JButton nvBouton = new JButton("Bouton " + (i+nbBoutons));
contenu.add(nvBouton);
contenu.validate();
nvBouton.addActionListener(new EcouteGeneral());

}

nbBoutons += 3;

Ici, le code
nvBouton.addActionListener(new EcouteGeneral());
sert à rajouter un écouteur sur chacun des nouveaux boutons créés. Remarquez que la variable qui contient la référence des nouveaux boutons est toujours la même ("nvBouton"), ce qui signifie que je ne pourrai pas, ultérieurement, me référer aux boutons facilement (quand je veux les désactiver, par exemple). Heureusement, une méthode existe déjà qui permet de savoir de quel bouton provient le clic (méthode "getSource()" de l'évènement).

La méthode principale pour désactiver les boutons est la suivante:

public void actionPerformed(ActionEvent ev) {

JButton source = (JButton) ev.getSource();
source.setEnabled(false);

}


Télécharger le code source

Si vous êtes curieux et voulez voir un peu, vous pouvez télécharger les sources ici


Note finale

Vous n'avez jamais fait de Java, et vous n'avez rien compris? Bienvenue dans le club... côté intuition et facilité d'approche, j'ai déjà vu mieux honnêtement. Par contre, j'aime quand même ça!

1 commentaire:

Nicolas a dit...

C'est cool le Java, mais pour les interfaces graphiques, on dirait que ça a été artificiellement ajouté au langage, c'est pas intuitif trop trop je trouve...